代码随想录算法训练营第五十六天|110.字符串接龙、105、有向图的完全可达性、106.岛屿的周长

110.字符串接龙

在这里插入图片描述
在这里插入图片描述

题目链接:110.字符串接龙
文档讲解:代码随想录
状态:用dfs搞了半天没整出来

思路:

这道题要解决两个问题:

  1. 图中的线是如何连在一起的:判断点与点之间的关系,需要判断是不是差一个字符,如果差一个字符,那就是有链接。
  2. 起点和终点的最短路径长度:无向图求最短路,广搜最为合适,广搜只要搜到了终点,那么一定是最短的路径。

注意点:

  1. 本题是一个无向图,需要用标记位,标记着节点是否走过,否则就会死循环!
  2. 使用set来检查字符串是否出现在字符串集合里更快一些

题解:

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(); // 读取目标字符串
        HashSet<String> wordSet = new HashSet<>(); // 字符串集合,使用HashSet存储以便于快速查找
        for (int i = 0; i < n; i++) {
            wordSet.add(scanner.next()); // 将输入的字符串添加到集合中
        }
        HashSet<String> visitedSet = new HashSet<>(); // 记录已经访问过的字符串

        Deque<String> deque = new LinkedList<>(); // 双端队列用于BFS
        deque.addLast(beginStr); // 将初始字符串加入队列

        // 初始化visitedSet
        visitedSet.add(beginStr); // 将初始字符串标记为已访问

        // 开始BFS搜索
        int steps = 1; // 初始字符串的转换步骤数为1
        while (!deque.isEmpty()) {
            int size = deque.size(); // 当前层的节点数
            for (int k = 0; k < size; k++) {
                String word = deque.pollFirst(); // 从队列头部取出当前字符串

                // 遍历当前字符串的每个字符位置
                for (int i = 0; i < word.length(); i++) {
                    char[] chars = word.toCharArray(); // 将字符串转为字符数组,便于逐字符修改
                    // 尝试将当前字符替换为'a'到'z'的所有字符
                    for (char j = 'a'; j <= 'z'; j++) {
                        chars[i] = j; // 替换字符
                        String newWord = new String(chars); // 形成新的字符串
                        if (newWord.equals(word)) {
                            continue; // 如果新字符串和当前字符串相同,则跳过
                        }
                        if (newWord.equals(endStr)) {
                            System.out.println(steps + 1); // 如果新字符串是目标字符串,则输出结果
                            return;
                        }
                        // 如果新字符串在字符串集合中且未被访问过
                        if (wordSet.contains(newWord) && !visitedSet.contains(newWord)) {
                            visitedSet.add(newWord); // 记录新字符串为已访问
                            deque.addLast(newWord); // 将新字符串加入队列
                        }
                    }
                }
            }
            steps++; // 每遍历完一层,步数加一
        }
    }
}

105.有向图的完全可达性

在这里插入图片描述
在这里插入图片描述

题目链接:105.有向图的完全可达性
文档讲解:代码随想录
状态:不会

思路:

  1. 先用邻接矩阵或者邻接表存放图的关系
  2. 使用dfs或者bfs遍历临界矩阵或邻接表

题解:

    public class Main {
        public static void main(String[] args) {
            // 创建Scanner对象以读取输入
            Scanner scanner = new Scanner(System.in);
            // 读取顶点数量n和边数量k
            int n = scanner.nextInt();
            int k = scanner.nextInt();
            // 初始化图的邻接矩阵
            int[][] graph = new int[n + 1][n + 1];
            // 初始化访问数组
            boolean[] visited = new boolean[n + 1];
            // 读取每条边并在邻接矩阵中记录
            for (int i = 0; i < k; i++) {
                int from = scanner.nextInt();
                int to = scanner.nextInt();
                graph[from][to] = 1;
            }
            // 从节点1开始进行深度优先搜索
            dfs(graph, visited, 1, n);
            // 检查所有节点是否都被访问过
            for (int i = 1; i < visited.length; i++) {
                if (!visited[i]) {
                    // 如果有节点未被访问过,则输出-1
                    System.out.println(-1);
                    return;
                }
            }
            // 如果所有节点都被访问过,则输出1
            System.out.println(1);
        }

        // 深度优先搜索函数
        public static void dfs(int[][] graph, boolean[] visited, int node, int n) {
            if (visited[node]) {
                return;
            }
            // 将当前节点标记为已访问
            visited[node] = true;
            // 遍历所有可能的下一个节点
            for (int i = 1; i <= n; i++) {
                // 如果可以从节点1-->i,就继续递归遍历能否从i到n
                // 如果节点未被访问且存在从当前节点到该节点的边
                if (!visited[i] && graph[node][i] == 1) {
                    // 递归进行深度优先搜索
                    dfs(graph, visited, i, n);
                }
            }
        }
    }

106.岛屿的周长

在这里插入图片描述
在这里插入图片描述

题目链接:106.岛屿的周长
文档讲解:代码随想录
状态:不会

思路:这道题不用dfs,bfs。。。
遍历每一个空格,遇到岛屿则计算其上下左右的空格情况。
如果该陆地上下左右的空格是有水域,则说明是一条边,如果该陆地上下左右的空格出界了,说明也是一条边。

题解:

public class Main {

    // 定义方向数组,表示右,下,左,上四个方向
    public static int[][] dir = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};

    public static void main(String[] args) {
        // 创建Scanner对象以读取输入
        Scanner scanner = new Scanner(System.in);
        // 读取网格的行数n和列数m
        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 res = 0;
        // 遍历网格中的每个单元格
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                // 如果当前单元格是陆地
                if (grid[i][j] == 1) {
                    // 检查当前单元格的四个方向
                    for (int k = 0; k < 4; k++) {
                        int x = i + dir[k][0];
                        int y = j + dir[k][1];
                        // 如果当前单元格在边界上,或周围是水,则周长加1
                        if (x < 0 || x >= n || y < 0 || y >= m || grid[x][y] == 0) {
                            res++;
                        }
                    }
                }
            }
        }
        // 输出岛屿的周长
        System.out.println(res);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值