代码随想录算法训练营第 53 天|110. 字符串接龙 105. 有向图的完全可达性 106、岛屿的周长
110. 字符串接龙
题目链接:https://kamacoder.com/problempage.php?pid=1183
题目描述:
字典 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。
输入示例
6
abc def
efc
dbc
ebc
dec
dfc
yhn
输出示例
4
提示信息
从 startStr 到 endStr,在 strList 中最短的路径为 abc -> dbc -> dec -> def,所以输出结果为 4,如图:
数据范围:
2 <= N <= 500
思路:
图论
代码:
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存储遍历到的字符串以及所走过的路径path
HashMap<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);
}
}
105. 有向图的完全可达性
题目链接:https://kamacoder.com/problempage.php?pid=1177
题目描述:
给定一个有向图,包含 N 个节点,节点编号分别为 1,2,…,N。现从 1 号节点开始,如果可以从 1 号节点的边可以到达任何节点,则输出 1,否则输出 -1。
输入描述
第一行包含两个正整数,表示节点数量 N 和边的数量 K。 后续 K 行,每行两个正整数 s 和 t,表示从 s 节点有一条边单向连接到 t 节点。
输出描述
如果可以从 1 号节点的边可以到达任何节点,则输出 1,否则输出 -1。
输入示例
4 4
1 2
2 1
1 3
2 4
输出示例
1
提示信息
从 1 号节点可以到达任意节点,输出 1。
数据范围:
1 <= N <= 100;
1 <= K <= 2000。
思路:
图论
代码:
#include <iostream>
#include <vector>
#include <list>
using namespace std;
void dfs(const vector<list<int>>& graph, int key, vector<bool>& visited) {
if (visited[key]) {
return;
}
visited[key] = true;
list<int> keys = graph[key];
for (int key : keys) {
// 深度优先搜索遍历
dfs(graph, key, visited);
}
}
int main() {
int n, m, s, t;
cin >> n >> m;
// 节点编号从1到n,所以申请 n+1 这么大的数组
vector<list<int>> graph(n + 1); // 邻接表
while (m--) {
cin >> s >> t;
// 使用邻接表 ,表示 s -> t 是相连的
graph[s].push_back(t);
}
vector<bool> visited(n + 1, false);
dfs(graph, 1, visited);
//检查是否都访问到了
for (int i = 1; i <= n; i++) {
if (visited[i] == false) {
cout << -1 << endl;
return 0;
}
}
cout << 1 << endl;
}
106、岛屿的周长
题目链接:https://kamacoder.com/problempage.php?pid=1178
题目描述:
给定一个由 1(陆地)和 0(水)组成的矩阵,岛屿是被水包围,并且通过水平方向或垂直方向上相邻的陆地连接而成的。
你可以假设矩阵外均被水包围。在矩阵中恰好拥有一个岛屿,假设组成岛屿的陆地边长都为 1,请计算岛屿的周长。岛屿内部没有水域。
输入描述
第一行包含两个整数 N, M,表示矩阵的行数和列数。之后 N 行,每行包含 M 个数字,数字为 1 或者 0,表示岛屿的单元格。
输出描述
输出一个整数,表示岛屿的周长。
输入示例
5 5
0 0 0 0 0
0 1 0 1 0
0 1 1 1 0
0 1 1 1 0
0 0 0 0 0
输出示例
14
提示信息
岛屿的周长为 14。
数据范围:
1 <= M, N <= 50。
思路:
图论
代码:
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);
}
}
for (int j = 0; j < N; j++) {
if (grid[i][j] == 1) {
count = 0;
helper(grid, i, j);
// 更新总周长
result += count;
}
}
}
// 打印结果
System.out.println(result);
}
}
######
######