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;}//如果最终的字符串不存在基因库中就返回-1if(!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;} }