力扣热门算法题 127.单词接龙,128.最长连续序列,130.被围绕的区域
力扣热门算法题 127.单词接龙,128.最长连续序列,130.被围绕的区域,每题做详细思路梳理,配套Python&Java双语代码, 2025.07 可通过leetcode所有测试用例。
目录
127.单词接龙
解题思路
完整代码
128.最长连续序列
解题思路
完整代码
130.被围绕的区域
解题思路
完整代码
127.单词接龙
字典
wordList
中从单词beginWord
到endWord
的 转换序列 是一个按下述规格形成的序列beginWord -> s1 -> s2 -> ... -> sk
:
- 每一对相邻的单词只差一个字母。
- 对于
1 <= i <= k
时,每个si
都在wordList
中。注意,beginWord
不需要在wordList
中。sk == endWord
给你两个单词
beginWord
和endWord
和一个字典wordList
,返回 从beginWord
到endWord
的 最短转换序列 中的 单词数目 。如果不存在这样的转换序列,返回0
。示例 1:
输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"] 输出:5 解释:一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog", 返回它的长度 5。示例 2:
输入:beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"] 输出:0 解释:endWord "cog" 不在字典中,所以无法进行转换。提示:
1 <= beginWord.length <= 10
endWord.length == beginWord.length
1 <= wordList.length <= 5000
wordList[i].length == beginWord.length
beginWord
、endWord
和wordList[i]
由小写英文字母组成beginWord != endWord
wordList
中的所有字符串 互不相同
解题思路
BFS 图搜索
每个单词看作图中的一个节点,相差一个字母的单词之间有边。
我们从 beginWord
开始,通过广度优先搜索,直到找到 endWord
。
-
先将 wordList 存入 set(便于 O(1) 查询)
-
如果
endWord
不在其中,直接返回 0
-
-
使用队列进行 BFS
-
初始放入
(beginWord, 1)
表示当前单词、路径长度为 1 -
每次出队:
-
对当前单词的每一位尝试 26 个小写字母变换;
-
如果变换后的单词在 wordList 中,就加入队列,继续 BFS;
-
同时从 set 中移除,避免重复访问。
-
-
-
搜索直到找到 endWord,返回当前路径长度
完整代码
python
class Solution:def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int:from typing import List
from collections import dequeclass Solution:def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int:wordSet = set(wordList)if endWord not in wordSet:return 0queue = deque([(beginWord, 1)])while queue:word, length = queue.popleft()for i in range(len(word)):for c in 'abcdefghijklmnopqrstuvwxyz':newWord = word[:i] + c + word[i+1:]if newWord == endWord:return length + 1if newWord in wordSet:wordSet.remove(newWord)queue.append((newWord, length + 1))return 0
java
import java.util.*;class Solution {public int ladderLength(String beginWord, String endWord, List<String> wordList) {Set<String> wordSet = new HashSet<>(wordList);if (!wordSet.contains(endWord)) return 0;Queue<String> queue = new LinkedList<>();queue.offer(beginWord);int steps = 1;while (!queue.isEmpty()) {int size = queue.size();while (size-- > 0) {String word = queue.poll();for (int i = 0; i < word.length(); i++) {char[] chars = word.toCharArray();for (char c = 'a'; c <= 'z'; c++) {chars[i] = c;String newWord = new String(chars);if (newWord.equals(endWord)) return steps + 1;if (wordSet.contains(newWord)) {queue.offer(newWord);wordSet.remove(newWord);}}}}steps++;}return 0;}
}
128.最长连续序列
给定一个未排序的整数数组
nums
,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。请你设计并实现时间复杂度为
O(n)
的算法解决此问题。示例 1:
输入:nums = [100,4,200,1,3,2] 输出:4 解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。示例 2:
输入:nums = [0,3,7,2,5,8,4,6,0,1] 输出:9示例 3:
输入:nums = [1,0,1,2] 输出:3提示:
0 <= nums.length <= 10^5
-10^9 <= nums[i] <= 10^9
解题思路
核心思路:
-
把所有数字放入哈希集合
numSet
中; -
只有当前数
x
是某个序列的起点(即x-1
不在集合中)时,才尝试向右扩展找x+1, x+2, ...
; -
每次尝试找最长的一段
[x, x+1, ..., x+k]
,记录最长长度。
完整代码
python
class Solution:def longestConsecutive(self, nums: List[int]) -> int:num_set = set(nums)longest = 0for num in num_set:if num - 1 not in num_set: # 只有起点才尝试向右找current = numstreak = 1while current + 1 in num_set:current += 1streak += 1longest = max(longest, streak)return longest
java
import java.util.*;class Solution {public int longestConsecutive(int[] nums) {Set<Integer> numSet = new HashSet<>();for (int num : nums) numSet.add(num);int longest = 0;for (int num : numSet) {if (!numSet.contains(num - 1)) { // 是起点int current = num;int streak = 1;while (numSet.contains(current + 1)) {current++;streak++;}longest = Math.max(longest, streak);}}return longest;}
}
130.被围绕的区域
给你一个
m x n
的矩阵board
,由若干字符'X'
和'O'
组成,捕获 所有 被围绕的区域:
- 连接:一个单元格与水平或垂直方向上相邻的单元格连接。
- 区域:连接所有
'O'
的单元格来形成一个区域。- 围绕:如果您可以用
'X'
单元格 连接这个区域,并且区域中没有任何单元格位于board
边缘,则该区域被'X'
单元格围绕。通过 原地 将输入矩阵中的所有
'O'
替换为'X'
来 捕获被围绕的区域。你不需要返回任何值。示例 1:
输入:board = [["X","X","X","X"],["X","O","O","X"],["X","X","O","X"],["X","O","X","X"]]
输出:[["X","X","X","X"],["X","X","X","X"],["X","X","X","X"],["X","O","X","X"]]
解释:
在上图中,底部的区域没有被捕获,因为它在 board 的边缘并且不能被围绕。
示例 2:
输入:board = [["X"]]
输出:[["X"]]
提示:
m == board.length
n == board[i].length
1 <= m, n <= 200
board[i][j]
为'X'
或'O'
解题思路
有点像围棋。。。
-
从四条边出发,找出所有不该被变成
'X'
的'O'
:-
用 DFS 或 BFS 从边缘的
'O'
向内部搜索,把它们“染色”为特殊字符(如'#'
)。
-
-
遍历整个棋盘:
-
将剩下的
'O'
(没有被染色的)说明是被包围的,替换为'X'
; -
把被染色成
'#'
的恢复成'O'
。
-
完整代码
python
from typing import Listclass Solution:def solve(self, board: List[List[str]]) -> None:if not board or not board[0]:returnm, n = len(board), len(board[0])def dfs(i, j):if i < 0 or i >= m or j < 0 or j >= n or board[i][j] != 'O':returnboard[i][j] = '#' # 临时标记为不需要变的dfs(i + 1, j)dfs(i - 1, j)dfs(i, j + 1)dfs(i, j - 1)# 从边界出发做 DFS,标记连通的 'O'for i in range(m):if board[i][0] == 'O':dfs(i, 0)if board[i][n - 1] == 'O':dfs(i, n - 1)for j in range(n):if board[0][j] == 'O':dfs(0, j)if board[m - 1][j] == 'O':dfs(m - 1, j)# 扫描全图,处理剩下的for i in range(m):for j in range(n):if board[i][j] == 'O':board[i][j] = 'X' # 被包围的elif board[i][j] == '#':board[i][j] = 'O' # 恢复原样
java
class Solution {public void solve(char[][] board) {int m = board.length;int n = board[0].length;if (m == 0 || n == 0) return;// 从边缘开始染色for (int i = 0; i < m; i++) {dfs(board, i, 0);dfs(board, i, n - 1);}for (int j = 0; j < n; j++) {dfs(board, 0, j);dfs(board, m - 1, j);}// 全图遍历替换for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (board[i][j] == 'O') {board[i][j] = 'X';} else if (board[i][j] == '#') {board[i][j] = 'O';}}}}private void dfs(char[][] board, int i, int j) {int m = board.length, n = board[0].length;if (i < 0 || i >= m || j < 0 || j >= n || board[i][j] != 'O') return;board[i][j] = '#';dfs(board, i + 1, j);dfs(board, i - 1, j);dfs(board, i, j + 1);dfs(board, i, j - 1);}
}