1、迷宫中离入口最近的出口 - 力扣(LeetCode)
思路:
- 利用BFS层序遍历,新建一个变量统计步数
- 代码:
class Solution { int dx[] = {0, 0, -1, 1}; int dy[] = {1, -1, 0, 0}; public int nearestExit(char[][] maze, int[] entrance) { int m = maze.length; int n = maze[0].length; boolean[][] vis = new boolean[m][n]; Queue<int[]> q = new LinkedList<>(); q.offer(new int[]{entrance[0], entrance[1]}); vis[entrance[0]][entrance[1]] = true; int step = 0; while(!q.isEmpty()){ step++; int sz = q.size(); for(int i = 0; i < sz; i++){ int[] t = q.poll(); int a = t[0]; int b = t[1]; for(int j = 0; j < 4; j++){ int x = a + dx[j]; int y = b + dy[j]; if(x >= 0 && x < m && y >= 0 && y < n && maze[x][y] == '.' && !vis[x][y]){ //判断是否已经走到出口 if(x == 0 || x == m - 1 || y == 0 || y == n - 1){ return step; } q.add(new int[]{x,y}); vis[x][y] = true; } } } } return -1; } }
2、最小基因变化 - 力扣(LeetCode)
思路:
- 用哈希表来标记搜索过的状态
- 遍历原字符串每一位,改成ACGT,再判断是否合法和是否已经出现过
- 利用哈希表判断是否在基因库中
- 代码:
class Solution { public int minMutation(String startGene, String endGene, String[] bank) { //用来标记已经搜索过的状态 Set<String> vis = new HashSet<>(); //用来统计基因库中的字符串便于判断 Set<String> hash = new HashSet<>(); for(String x : bank){ hash.add(x); } char[] change = {'A', 'C', 'G', 'T'}; //如果初识和最终相等就直接返回 if(startGene.equals(endGene)){ return 0; } //如果最终的字符串不存在基因库中就返回-1 if(!hash.contains(endGene)){ return -1; } Queue<String> q = new LinkedList<>(); q.add(startGene); vis.add(startGene); int step = 0; while(!q.isEmpty()){ step++; int sz = q.size(); //队列的长度 while(sz-- != 0){ String t = q.poll(); for(int i = 0; i < 8; i++){ char[] tmp = t.toCharArray(); for(int j = 0; j < 4; j++){ tmp[i] = change[j]; String next = new String(tmp); //符合在基因库且没有出现过 if(hash.contains(next) && !vis.contains(next)){ //判断如果和最终相等就直接返回步数 if(next.equals(endGene)){ return step; } q.add(next); vis.add(next); } } } } } return -1; } }
3、单词接龙 - 力扣(LeetCode)
思路:
- 与上一题的思路一样,这道题的范围是‘a’ ~ ‘z’
- 返回的长度就是在步数加一
- 代码:
class Solution { public int ladderLength(String beginWord, String endWord, List<String> wordList) { Set<String> vis = new HashSet<>(); Set<String> hash = new HashSet<>(); for(String x : wordList){ hash.add(x); } if(beginWord.equals(endWord)){ return 0; } if(!hash.contains(endWord)){ return 0; } Queue<String> q = new LinkedList<>(); q.offer(beginWord); vis.add(beginWord); int len = 0; while(!q.isEmpty()){ len++; int sz = q.size(); while(sz-- != 0){ String t = q.poll(); for(int i = 0; i < beginWord.length(); i++){ char[] tmp = t.toCharArray(); for(char ch = 'a'; ch <= 'z'; ch++){ tmp[i] = ch; String next = new String(tmp); if(hash.contains(next) && !vis.contains(next)){ if(endWord.equals(next)){ return len+1; } q.offer(next); vis.add(next); } } } } } return 0; } }
4、为高尔夫比赛砍树 - 力扣(LeetCode)
思路:
- 按照树的由低到高来砍树,可以转换成数字低到高的最短路径之和
- 先将所以值排序,按照从小到大的最短路径遍历
- 代码:
class Solution { int m, n; public int cutOffTree(List<List<Integer>> f) { m = f.size(); n = f.get(0).size(); //1、准备工作确定砍树的顺序 List<int[]> trees = new ArrayList<>(); for(int i = 0; i < m; i++){ for(int j = 0; j < n; j++){ if(f.get(i).get(j) > 1){ trees.add(new int[]{i, j}); } } } //排序 Collections.sort(trees, (a,b) ->{ return f.get(a[0]).get(a[1]) - f.get(b[0]).get(b[1]); }); //2、按照顺序砍树 int ret = 0; int bx = 0, by = 0; for(int[] tree : trees){ int x = tree[0]; int y = tree[1]; int step = bfs(f, bx, by, x, y); if(step == -1){ return -1; } ret += step; bx = x; by = y; } return ret; } int[] dx = {0, 0, -1, 1}; int[] dy = {-1, 1, 0, 0}; public int bfs(List<List<Integer>> f, int bx, int by, int ex, int ey){ if(bx == ex && by == ey){ return 0; } Queue<int[]> q = new LinkedList<>(); boolean[][] vis = new boolean[m][n]; q.add(new int[]{bx, by}); vis[bx][by] = true; int step = 0; while(!q.isEmpty()){ step++; int sz = q.size(); while(sz-- != 0){ int[] t = q.poll(); int a = t[0]; int b = t[1]; for(int i = 0; i < 4; i++){ int x = a + dx[i]; int y = b + dy[i]; if(x >= 0 && x < m && y >= 0 && y < n && f.get(x).get(y) != 0 && !vis[x][y]){ if(x == ex && y == ey ){ return step; } q.add(new int[]{x,y}); vis[x][y] = true; } } } } return -1; } }