110.字符串接龙
题目:110. 字符串接龙 (kamacoder.com)
思路:没有思路
答案
import java.util.*;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();String beginStr = scanner.next();String endStr = scanner.next();Set<String> strSet = new HashSet<>();for (int i = 0; i < n; i++) {strSet.add(scanner.next());}System.out.println(findShortestTransformation(beginStr, endStr, strSet));}private static int findShortestTransformation(String beginStr, String endStr, Set<String> strSet) {// 记录strSet里的字符串是否被访问过,同时记录路径长度Map<String, Integer> visitMap = new HashMap<>();// 初始化队列Queue<String> queue = new LinkedList<>();queue.add(beginStr);// 初始化visitMapvisitMap.put(beginStr, 1);while (!queue.isEmpty()) {String word = queue.poll();int pathLength = visitMap.get(word); // 这个字符串在路径中的长度// 开始在这个str中,挨个字符去替换for (int i = 0; i < word.length(); i++) {char[] newWordArray = word.toCharArray();// 遍历26个字母for (char j = 'a'; j <= 'z'; j++) {newWordArray[i] = j;String newWord = new String(newWordArray);if (newWord.equals(endStr)) { // 发现替换字母后,字符串与终点字符串相同return pathLength + 1; // 找到了路径}// 字符串集合里出现了newWord,并且newWord没有被访问过if (strSet.contains(newWord) && !visitMap.containsKey(newWord)) {// 添加访问信息,并将新字符串放到队列中visitMap.put(newWord, pathLength + 1);queue.add(newWord);}}}}// 没找到输出0return 0;}
}
小结
- 使用 Set<String> 存储字符串
- 使用 Map<String, Integer> 记录是否访问过,以及路径长度
- 通过queue来存储遍历过的字符串,从beginStr开始,每次替换一个字符,要是替换后的字符串存在于set中,就将该字符串记录为已访问,并将字符串放入到queue中
105.有向图的完全可达性
题目:105. 有向图的完全可达性 (kamacoder.com)
思路:从1出发,进行深搜,走完所有路径,看是否能够到达所有节点
尝试(运行出错)
import java.util.*;public class Main {private static List<List<Integer>> adjList;private static List<List<Integer>> allPaths;private static int target;public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();int m = scanner.nextInt();adjList = new ArrayList<>();for (int i = 0; i < n + 1; i++) {adjList.add(new ArrayList<>());}for (int i = 0; i < m; i++) {int s = scanner.nextInt();int t = scanner.nextInt();adjList.get(s).add(t);}for(int i =2; i<=n; i++){target = i;allPaths = new ArrayList<>();List<Integer> currentPath = new ArrayList<>();currentPath.add(1);findAllPaths(1, currentPath);if(allPaths.isEmpty()){System.out.println("-1");}}System.out.println("1");scanner.close();}private static void findAllPaths(int currentNode, List<Integer> currentPath) {if (currentNode == target) {allPaths.add(new ArrayList<>(currentPath));return;}for (int nextNode : adjList.get(currentNode)) {currentPath.add(nextNode);findAllPaths(nextNode, currentPath);currentPath.remove(currentPath.size() - 1);}}}
答案
import java.util.*;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt(); // 节点数量int m = scanner.nextInt(); // 边的数量// 节点编号从1到n,所以申请 n+1 这么大的数组List<List<Integer>> graph = new ArrayList<>(n + 1);for (int i = 0; i <= n; i++) {graph.add(new ArrayList<>());}// 读取边的信息并构建邻接表for (int i = 0; i < m; i++) {int s = scanner.nextInt();int t = scanner.nextInt();graph.get(s).add(t);}// 初始化访问数组boolean[] visited = new boolean[n + 1];dfs(graph, 1, visited);// 检查是否所有节点都被访问到了for (int i = 1; i <= n; i++) {if (!visited[i]) {System.out.println(-1);return;}}System.out.println(1);}private static void dfs(List<List<Integer>> graph, int node, boolean[] visited) {if (visited[node]) {return;}visited[node] = true;for (int neighbor : graph.get(node)) {dfs(graph, neighbor, visited);}}
}
小结
通过递归, 把所有路径跑一遍, 之后再检查是否所有的节点都有被访问到, 此处不需要回溯
106.岛屿的周长
题目:106. 岛屿的周长 (kamacoder.com)
思路:逐个遍历1,计算每个1跟临近的0所形成的边界,加起来,就是周长
尝试(示例输出正确,提交后输出错误)
import java.util.*;class Main{public static int n;public static int m;public static int[][] grid;public static void main(String[] args){Scanner scanner = new Scanner(System.in);n = scanner.nextInt();m = scanner.nextInt();grid = new int[n][m];for(int i=0; i<n; i++){for(int j=0; j<m; j++){grid[i][j] = scanner.nextInt(); }}int maxArea = 0;for(int i=0; i<n; i++){for(int j=0; j<m; j++){maxArea+=count(i,j); }}System.out.println(maxArea);}public static int count(int i,int j){if(grid[i][j]!=1) return 0;int len = 0;if(grid[i-1][j]==0){len++;}if(grid[i+1][j]==0){len++;}if(grid[i][j-1]==0){len++;}if(grid[i][j+1]==0){len++;}return len;}
}
答案
import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt(); // 行数int m = scanner.nextInt(); // 列数int[][] grid = new int[n][m];for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {grid[i][j] = scanner.nextInt();}}int landCount = 0; // 陆地数量int neighborCount = 0; // 相邻陆地的数量for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (grid[i][j] == 1) {landCount++; // 统计总的陆地数量// 统计上边相邻陆地if (i - 1 >= 0 && grid[i - 1][j] == 1) neighborCount++;// 统计左边相邻陆地if (j - 1 >= 0 && grid[i][j - 1] == 1) neighborCount++;// 下边和右边的相邻陆地不统计是为了避免重复计算}}}// 计算岛屿的周长int perimeter = landCount * 4 - neighborCount * 2;System.out.println(perimeter);}
}
小结
注意每次只统计上边和左边的相邻陆地