当前位置: 首页 > news >正文

Day47 | 110.字符串接龙 105.有向图的完全可达性 106.岛屿的周长

110.字符串接龙

110. 字符串接龙

题目

题目描述

字典 strList 中从字符串 beginStr 和 endStr 的转换序列是一个按下述规格形成的序列: 

1. 序列中第一个字符串是 beginStr。

2. 序列中最后一个字符串是 endStr。 

3. 每次转换只能改变一个字符。 

4. 转换过程中的中间字符串必须是字典 strList 中的字符串,且strList里的每个字符串只用使用一次。 

给你两个字符串 beginStr 和 endStr 和一个字典 strList,找到从 beginStr 到 endStr 的最短转换序列中的字符串数目。如果不存在这样的转换序列,返回 0。

输入描述

第一行包含一个整数 N,表示字典 strList 中的字符串数量。 第二行包含两个字符串,用空格隔开,分别代表 beginStr 和 endStr。 后续 N 行,每行一个字符串,代表 strList 中的字符串。

输出描述

输出一个整数,代表从 beginStr 转换到 endStr 需要的最短转换序列中的字符串数量。如果不存在这样的转换序列,则输出 0。

思路

  1. 初始化
    • 使用HashSetset)来存储wordList中的所有单词,以便快速检查某个单词是否存在于列表中。
    • 使用Queuequeue)来存储待处理的单词,这些单词是当前已经找到但尚未探索完所有可能变化的单词。
    • 使用HashMapvisitMap)来记录每个单词被访问时的路径长度(即距离起始单词的步数)。
  2. BFS过程
    • 将起始单词加入队列和访问记录中,并设置其路径长度为1。
    • 循环处理队列中的单词,直到队列为空。
    • 对于每个单词,尝试替换其每个位置的字符为'a'到'z'之间的所有字符,生成新的单词。
    • 检查新单词是否为目标单词,如果是,则返回当前路径长度加1。
    • 如果新单词存在于set中且之前未被访问过,则将其加入队列和访问记录中,并更新其路径长度。
  3. 结果
    • 如果遍历完所有可能的单词后仍未找到目标单词,则返回0,表示无法从起始单词到达目标单词。

代码

import java.util.*;public class Main {// BFS方法public static int ladderLength(String beginWord, String endWord, List<String> wordList) {// 使用set作为查询容器,效率更高HashSet<String> set = new HashSet<>(wordList);// 声明一个queue存储每次变更一个字符得到的且存在于容器中的新字符串Queue<String> queue = new LinkedList<>();// 声明一个hashMap存储遍历到的字符串以及所走过的路径pathHashMap<String, Integer> visitMap = new HashMap<>();queue.offer(beginWord);visitMap.put(beginWord, 1);while (!queue.isEmpty()) {String curWord = queue.poll();int path = visitMap.get(curWord);for (int i = 0; i < curWord.length(); i++) {char[] ch = curWord.toCharArray();// 每个位置尝试26个字母for (char k = 'a'; k <= 'z'; k++) {ch[i] = k;String newWord = new String(ch);if (newWord.equals(endWord)) return path + 1;// 如果这个新字符串存在于容器且之前未被访问到if (set.contains(newWord) && !visitMap.containsKey(newWord)) {visitMap.put(newWord, path + 1);queue.offer(newWord);}}}}return 0;}public static void main (String[] args) {/* code */// 接收输入Scanner sc = new Scanner(System.in);int N = sc.nextInt();sc.nextLine();String[] strs = sc.nextLine().split(" ");List<String> wordList = new ArrayList<>();for (int i = 0; i < N; i++) {wordList.add(sc.nextLine());}// wordList.add(strs[1]);// 打印结果int result = ladderLength(strs[0], strs[1], wordList);System.out.println(result);}
}

易错点

  1. 输入处理
    • 在读取N(单词列表的大小)后,需要调用sc.nextLine()来跳过行尾的换行符,否则在读取第一个单词时会出错。
    • 题目中可能未明确说明,但通常假设strs[0]是起始单词,strs[1]是目标单词,而剩余的单词在wordList中。然而,在你的代码中,你直接从sc.nextLine()读取了所有单词(除了N),这可能不是题目意图。你应该根据题目要求来读取这些单词。
  2. 字符串处理
    • 在替换字符时,需要确保使用字符数组来避免在循环中多次创建新的字符串对象。
    • 替换字符后,应检查新生成的单词是否存在于set中且之前未被访问过。
  3. 边界条件
    • 如果wordList为空或未包含起始单词和目标单词,应返回适当的值(通常是0,表示无法到达)。
    • 如果起始单词和目标单词相同,应返回1(因为不需要任何变化)。

105.有向图的完全可达性

105. 有向图的完全可达性

题目

题目描述

给定一个有向图,包含 N 个节点,节点编号分别为 1,2,...,N。现从 1 号节点开始,如果可以从 1 号节点的边可以到达任何节点,则输出 1,否则输出 -1。

输入描述

第一行包含两个正整数,表示节点数量 N 和边的数量 K。 后续 K 行,每行两个正整数 s 和 t,表示从 s 节点有一条边单向连接到 t 节点。

输出描述

如果可以从 1 号节点的边可以到达任何节点,则输出 1,否则输出 -1。

思路

  1. 输入处理:首先,程序通过Scanner类读取图的节点数n和边数m。然后,它初始化一个大小为n+1List<List<Integer>>类型的邻接表graph,其中每个内部列表代表一个节点的所有邻居节点。由于节点编号从1开始,但数组索引从0开始,因此需要大小为n+1的列表数组。

  2. 构建邻接表:通过读取每对相连的节点st,将t添加到s的邻居列表中。注意,这里的st是节点编号,不是索引,因此它们可以直接用作graph的索引(尽管实际上它们被用作索引时减1,因为内部索引是从0开始的)。

  3. 深度优先搜索:从节点1开始进行深度优先搜索。在搜索过程中,使用一个布尔数组visited来跟踪哪些节点已经被访问过。对于每个节点,如果它尚未被访问,则标记为已访问,并递归地访问其所有邻居。

  4. 检查访问情况:在DFS完成后,程序遍历visited数组,检查是否有任何节点未被访问。如果有任何节点未被访问,则输出-1表示不是所有节点都可从起始节点访问;如果所有节点都被访问,则输出1

代码

import java.util.ArrayList;  
import java.util.Arrays;  
import java.util.List;  
import java.util.Scanner;  public class Main {  static void dfs(List<List<Integer>> graph, int key, boolean[] visited) {  if (visited[key]) {  return;  }  visited[key] = true;  List<Integer> keys = graph.get(key);  for (int neighbor : keys) {  // 深度优先搜索遍历  dfs(graph, neighbor, visited);  }  }  public static void main(String[] args) {  Scanner scanner = new Scanner(System.in);  int n = scanner.nextInt();  int m = scanner.nextInt();  // 节点编号从1到n,但数组索引从0开始,所以申请 n+1 这么大的数组  List<List<Integer>> graph = new ArrayList<>(n + 1);  for (int i = 0; i <= n; i++) {  graph.add(new ArrayList<>());  }  while (m-- > 0) {  int s = scanner.nextInt();  int t = scanner.nextInt();  // 使用邻接表 ,表示 s -> t 是相连的  graph.get(s).add(t);  }  boolean[] visited = new boolean[n + 1];  dfs(graph, 1, visited);  // 检查是否都访问到了  boolean allVisited = true;  for (int i = 1; i <= n; i++) {  if (!visited[i]) {  System.out.println(-1);  allVisited = false;  break;  }  }  if (allVisited) {  System.out.println(1);  }  scanner.close();  }  
}

易错点

  1. 索引与节点编号的混淆:在这个问题中,节点编号是从1开始的,但数组索引是从0开始的。这可能导致在处理输入时出错,尤其是当直接使用节点编号作为索引时。然而,在这个特定的代码中,由于graph的索引被正确地处理(即graph.get(s)中的s是节点编号,但内部自动减1以用作索引),这个错误被避免了。

  2. 邻接表的构建:在构建邻接表时,必须确保每个节点都有一个对应的空列表。在这个例子中,通过初始化一个大小为n+1ArrayList<ArrayList<Integer>>来确保这一点。

  3. DFS的递归深度:如果图是高度递归的(例如,存在很长的路径或循环),那么DFS可能会导致堆栈溢出。虽然在这个简单的例子中不太可能出现,但在处理大型或复杂的图时需要注意。

106.岛屿的周长

106. 岛屿的周长

题目

题目描述

给定一个由 1(陆地)和 0(水)组成的矩阵,岛屿是被水包围,并且通过水平方向或垂直方向上相邻的陆地连接而成的。

你可以假设矩阵外均被水包围。在矩阵中恰好拥有一个岛屿,假设组成岛屿的陆地边长都为 1,请计算岛屿的周长。岛屿内部没有水域。

输入描述

第一行包含两个整数 N, M,表示矩阵的行数和列数。之后 N 行,每行包含 M 个数字,数字为 1 或者 0,表示岛屿的单元格。

输出描述

输出一个整数,表示岛屿的周长。

思路

目的是计算一个二维网格中所有值为1的单元格的周长总和。程序首先通过标准输入接收网格的行数M和列数N,然后读取网格的具体内容(即每个单元格的值)。接下来,程序遍历整个网格,对于每个值为1的单元格,它调用helper函数来计算该单元格的周长,并将所有值为1的单元格的周长累加到result变量中。最后,程序输出总周长。

代码

import java.util.*;public class Main {// 每次遍历到1,探索其周围4个方向,并记录周长,最终合计// 声明全局变量,dirs表示4个方向static int[][] dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};// 统计每单个1的周长static int count;// 探索其周围4个方向,并记录周长public static void helper(int[][] grid, int x, int y) {for (int[] dir : dirs) {int nx = x + dir[0];int ny = y + dir[1];// 遇到边界或者水,周长加一if (nx < 0 || nx >= grid.length || ny < 0 || ny >= grid[0].length|| grid[nx][ny] == 0) {count++;}}}public static void main(String[] args) {Scanner sc = new Scanner(System.in);// 接收输入int M = sc.nextInt();int N = sc.nextInt();int[][] grid = new int[M][N];for (int i = 0; i < M; i++) {for (int j = 0; j < N; j++) {grid[i][j] = sc.nextInt();}}int result = 0; // 总周长for (int i = 0; i < M; i++) {for (int j = 0; j < N; j++) {if (grid[i][j] == 1) {count = 0;helper(grid, i, j);// 更新总周长result += count;}}}// 打印结果System.out.println(result);}
}

易错点

  1. 全局变量count的线程安全问题
    在这个程序中,count被用作全局变量来存储单个值为1的单元格的周长。由于Java的static变量是类级别的,而不是实例级别的,因此它在这个上下文中是安全的,因为程序是单线程的。然而,在多线程环境中,这种使用全局变量的方式可能会导致竞态条件。在这个特定程序中,由于不存在多线程,所以这不是一个问题。

  2. 边界条件处理
    helper函数正确地处理了边界条件和值为0的单元格,这是计算周长所必需的。然而,如果网格的大小(MN)为0或负数,程序将抛出异常。虽然这种情况在常规输入中不太可能发生,但最好添加一些额外的检查来确保输入的有效性。

总结

明天继续图论!

继续加油

成功的人不是赢在起点,而是坚持到终点

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • openGuass——一般元命令
  • Vue JS执行机制和nextTick
  • Python算法工程师面试整理-微积分
  • SAP商业地产管理(RE-FX)
  • 微信小程序如何存储值
  • 集成mybatis-plus框架
  • 3.3、matlab彩色图和灰度图的二值化算法汇总
  • 如何在不格式化的情况下解锁 Android 智能手机密码
  • ue5远程渲染和本地渲染的区别,及云渲染的联系
  • 【MySQL 11】索引 (带思维导图)
  • 8.4 数据库基础技术-SQL
  • http基础原理及应用
  • 【SQL】窗口函数sum() over ( partition by xx order by xx)
  • 基于game-based算法的动态频谱访问matlab仿真
  • 重构多重children数据 减少数据
  • 【347天】每日项目总结系列085(2018.01.18)
  • 2017 前端面试准备 - 收藏集 - 掘金
  • ECMAScript入门(七)--Module语法
  • javascript 哈希表
  • Java方法详解
  • nfs客户端进程变D,延伸linux的lock
  • unity如何实现一个固定宽度的orthagraphic相机
  • Yii源码解读-服务定位器(Service Locator)
  • 阿里云ubuntu14.04 Nginx反向代理Nodejs
  • 从setTimeout-setInterval看JS线程
  • 大快搜索数据爬虫技术实例安装教学篇
  • 关于extract.autodesk.io的一些说明
  • 机器人定位导航技术 激光SLAM与视觉SLAM谁更胜一筹?
  • 正则表达式小结
  • 正则学习笔记
  • hi-nginx-1.3.4编译安装
  • UI设计初学者应该如何入门?
  • ​​​【收录 Hello 算法】9.4 小结
  • ​LeetCode解法汇总2182. 构造限制重复的字符串
  • #数据结构 笔记三
  • $(this) 和 this 关键字在 jQuery 中有何不同?
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • (1)虚拟机的安装与使用,linux系统安装
  • (2024,Flag-DiT,文本引导的多模态生成,SR,统一的标记化,RoPE、RMSNorm 和流匹配)Lumina-T2X
  • (2024,Vision-LSTM,ViL,xLSTM,ViT,ViM,双向扫描)xLSTM 作为通用视觉骨干
  • (3)医疗图像处理:MRI磁共振成像-快速采集--(杨正汉)
  • (day18) leetcode 204.计数质数
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (Redis使用系列) Springboot 使用Redis+Session实现Session共享 ,简单的单点登录 五
  • (Redis使用系列) Springboot 使用redis实现接口Api限流 十
  • (翻译)Quartz官方教程——第一课:Quartz入门
  • (一)为什么要选择C++
  • (转)Linux NTP配置详解 (Network Time Protocol)
  • (转)详解PHP处理密码的几种方式
  • ***监测系统的构建(chkrootkit )
  • .net core 客户端缓存、服务器端响应缓存、服务器内存缓存
  • .NET Micro Framework初体验
  • .NET 回调、接口回调、 委托
  • .NET 将混合了多个不同平台(Windows Mac Linux)的文件 目录的路径格式化成同一个平台下的路径
  • .net8.0与halcon编程环境构建