力扣爆刷第93天之hot100五连刷51-55
文章目录
- 力扣爆刷第93天之hot100五连刷51-55
- 一、200. 岛屿数量
- 二、994. 腐烂的橘子
- 三、207. 课程表
- 四、208. 实现 Trie (前缀树)
- 五、46. 全排列
一、200. 岛屿数量
题目链接:https://leetcode.cn/problems/number-of-islands/description/?envType=study-plan-v2&envId=top-100-liked
思路:很经典的图论,广度优先和深度优先都可以,求岛屿数量关键是把遍历过的岛屿进行标记,避免重复遍历。
class Solution {public int numIslands(char[][] grid) {int count = 0;for(int i = 0; i < grid.length; i++) {for(int j = 0; j < grid[0].length; j++) {if(grid[i][j] == '1') {count++;dfs(grid, i, j);}}}return count;}void dfs(char[][] grid, int x, int y) {if(x < 0 || x >= grid.length || y < 0 || y >= grid[0].length) return ;if(grid[x][y] == '0') return;grid[x][y] = '0';dfs(grid, x - 1, y);dfs(grid, x + 1, y);dfs(grid, x, y - 1);dfs(grid, x, y + 1);}}
二、994. 腐烂的橘子
题目链接:https://leetcode.cn/problems/rotting-oranges/description/?envType=study-plan-v2&envId=top-100-liked
思路:本题是一个多源头同步扩散,所以需要使用广度优先,用队列来模拟二叉树的层序遍历,控制所有的源头进行一圈一圈的扩散。
class Solution {int count = 0;Deque<int[]> queue = new LinkedList<>();public int orangesRotting(int[][] grid) {int freeNum = 0;for(int i = 0; i < grid.length; i++) {for(int j = 0; j < grid[0].length; j++) {if(grid[i][j] == 1) {freeNum++;} if(grid[i][j] == 2) {queue.add(new int[]{i, j});}}}while(!queue.isEmpty()) {if(freeNum == 0) return count;count++;int size = queue.size();for(int i = 0; i < size; i++) {int[] temp = queue.poll();int x = temp[0], y = temp[1];freeNum -= roting(grid, x-1, y);freeNum -= roting(grid, x+1, y);freeNum -= roting(grid, x, y-1);freeNum -= roting(grid, x, y+1);}}return freeNum > 0 ? -1 : count;}int roting(int[][] grid, int x, int y) {if(x < 0 || y < 0 || x > grid.length - 1 || y > grid[0].length - 1 || grid[x][y] != 1) {return 0;}grid[x][y] = 2;queue.add(new int[]{x, y});return 1;}
}
三、207. 课程表
题目链接:https://leetcode.cn/problems/course-schedule/description/?envType=study-plan-v2&envId=top-100-liked
思路:根据题目要求需要构建邻接表,然后我们要判断邻接表是否成环,visited数组使用来记录访问过的节点,避免重复访问,flags数组是用来记录从任意一个节点出发是否成环,如果成环则无法完成课程表。
另外就是关于flags数组的使用,单纯的利用visisted是无法判断是否成环的,如下图只遍历邻接表的0和1会发现0重复遍历,但是不成换。。
class Solution {boolean[] visited;boolean[] flags;boolean hasCycle = false;public boolean canFinish(int numCourses, int[][] prerequisites) {visited = new boolean[numCourses];flags = new boolean[numCourses];List<Integer>[] graph = build(numCourses, prerequisites);for(int i = 0; i < numCourses; i++) {traverse(graph, i);}return !hasCycle;}void traverse(List<Integer>[] graph, int i) {if(flags[i]) {hasCycle = true;}if(visited[i] || hasCycle) return;visited[i] = true;flags[i] = true;for(int t : graph[i]) {traverse(graph, t);}flags[i] = false;}List<Integer>[] build(int numCourses, int[][] prerequisites) {List<Integer>[] graph = new ArrayList[numCourses];for(int i = 0; i < numCourses; i++) {graph[i] = new ArrayList();}for(int[] edge : prerequisites) {graph[edge[1]].add(edge[0]);}return graph;}
}
四、208. 实现 Trie (前缀树)
题目链接:https://leetcode.cn/problems/implement-trie-prefix-tree/description/?envType=study-plan-v2&envId=top-100-liked
思路:利用单词构建多叉树,然后遍历多叉树。
class Trie {Node root = null;class Node{int v = 0;Node[] child = new Node[26];}public Trie() {}public void insert(String word) {// if (search(word)) {// return;// }root = addNode(root, word, 0);}public boolean search(String word) {Node node = getNode(root, word);if (node == null || node.v == 0) {return false;}return true;}public boolean startsWith(String prefix) {return getNode(root, prefix) != null;}Node getNode(Node node, String word) {Node p = node;for (int i = 0; i < word.length(); i++) {if (p == null) {return null;}p = p.child[word.charAt(i)-'a'];}return p;}Node addNode(Node node, String word, int i) {if (node == null) {node = new Node();}if (i == word.length()) {node.v = 1;return node;}int c = word.charAt(i) - 'a';node.child[c] = addNode(node.child[c], word, i+1);return node;}
}/*** Your Trie object will be instantiated and called as such:* Trie obj = new Trie();* obj.insert(word);* boolean param_2 = obj.search(word);* boolean param_3 = obj.startsWith(prefix);*/
五、46. 全排列
题目链接:https://leetcode.cn/problems/permutations/description/?envType=study-plan-v2&envId=top-100-liked
思路:全排列不需要指定起始位置,只需要纵向去重即可。
class Solution {List<List<Integer>> arrayList = new ArrayList<>();List<Integer> list = new ArrayList<>();boolean[] visited;public List<List<Integer>> permute(int[] nums) {visited = new boolean[nums.length];backTracking(nums);return arrayList;}void backTracking(int[] nums) {if(list.size() == nums.length) {arrayList.add(new ArrayList(list));return;}for(int i = 0; i < nums.length; i++) {if(visited[i]) continue;visited[i] = true;list.add(nums[i]);backTracking(nums);visited[i] = false;list.remove(list.size()-1);}}}