class Solution:
def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int:
def addWord(word: str):
if word not in wordId:
nonlocal nodeNum # 声明 nodeNum 是外部函数的变量,当你需要在嵌套函数中修改外部函数的变量时,使用 nonlocal。
# 如果不使用 nonlocal,Python 会认为你在嵌套函数中创建了一个新的局部变量,而不是修改外部函数的变# 量。
wordId[word] = nodeNum
nodeNum += 1
def addEdge(word: str):
addWord(word)
id1 = wordId[word]
chars = list(word) # 将单词转换为列表
for i in range(len(chars)):
tmp = chars[i]
chars[i] = "*"
newWord = "".join(chars) # 将列表转换为字符串
addWord(newWord)
id2 = wordId[newWord]
edge[id1].append(id2)
edge[id2].append(id1)
chars[i] = tmp
wordId = dict()
edge = collections.defaultdict(list) # 创建一个默认字典,用于存储单词之间的边
nodeNum = 0
for word in wordList:
addEdge(word)
addEdge(beginWord)
if endWord not in wordId:
return 0
dis = [float("inf")] * nodeNum
beginId, endId = wordId[beginWord], wordId[endWord]
dis[beginId] = 0
que = collections.deque([beginId])
while que:
x = que.popleft()
if x == endId:
return dis[endId] // 2 + 1
for it in edge[x]:
if dis[it] == float("inf"):
dis[it] = dis[x] + 1
que.append(it)
return 0
defaultdict 的初始化:
edge = collections.defaultdict(list) 创建了一个 defaultdict,其默认值是一个空列表 []。
添加边的操作:
当调用 self.edge[id1].append(id2) 时,如果 id1 不存在于 edge 中,defaultdict 会自动创建 id1 键,并将其值初始化为一个空列表 [],然后再将 id2 添加到该列表中。
简化代码:
使用 defaultdict 可以避免手动检查键是否存在并初始化列表,使代码更加简洁和高效。
collections 是 Python 标准库中的一个模块,提供了许多有用的容器数据类型,旨在替代和扩展内置的通用容器类型,如 dict, list, set, 和 tuple。这些容器数据类型通常具有更高的性能和更多的功能,适用于各种编程场景。
from collections import deque, defaultdict
class Solution:
def __init__(self):
self.word_id = dict()
self.edge = []
self.node_num = 0
def addWord(self, word):
if word not in self.word_id:
self.word_id[word] = self.node_num
self.node_num += 1
self.edge.append([])
def addEdge(self, word1, word2):
id1 = self.word_id[word1]
id2 = self.word_id[word2]
self.edge[id1].append(id2)
self.edge[id2].append(id1)
def buildGraph(self, wordList):
for word in wordList:
self.addWord(word)
for word in wordList:
for i in range(len(word)):
for c in 'abcdefghijklmnopqrstuvwxyz':
new_word = word[:i] + c + word[i+1:]
if new_word in self.word_id and new_word != word:
self.addEdge(word, new_word)
def ladderLength(self, beginWord, endWord, wordList):
if endWord not in wordList:
return 0
# 添加 beginWord 到图中(如果不在 wordList 中)
if beginWord not in wordList:
wordList.append(beginWord)
self.buildGraph(wordList)
# BFS 初始化
queue = deque([(self.word_id[beginWord], 1)])
visited = set([self.word_id[beginWord]])
while queue:
current_id, level = queue.popleft()
if self.word_id[endWord] == current_id:
return level
for neighbor_id in self.edge[current_id]:
if neighbor_id not in visited:
visited.add(neighbor_id)
queue.append((neighbor_id, level + 1))
return 0
class Solution {
public:
unordered_map<string, int> wordId; //记录单词的Id
vector<vector<int>> edge; //每个单词作为一个节点
int nodenum = 0; //单词对应的编号
void addWord(string& word){
if(!wordId.count(word)){ //检查当前单词是否存入
wordId[word] = nodenum++;
edge.emplace_back();
}
}
void addEdge(string& word){ //给当前单词加入邻居
addWord(word); //检查当前单词是否有节点编号
int id1 = wordId[word]; //获取当前单词节点标号
for(char &it: word){
char temp = it;
it = '*'; //替换一个单词
addWord(word);
int id2 = wordId[word];
edge[id1].push_back(id2);
edge[id2].push_back(id1);
it = temp;
}
}
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
for(string &word: wordList){
addEdge(word);
}
addEdge(beginWord);
if(!wordId.count(endWord)){
return 0;
}
vector<int> dis(nodenum, INT_MAX);
int beginWordId = wordId[beginWord], endWordId = wordId[endWord];
dis[beginWordId] = 0; //自身到自身距离等于0
//开始广度搜索
queue<int> que;
que.push(beginWordId);
while(!que.empty()){
int x = que.front(); //开始找邻居节点标号计算距离
que.pop();
if(x == endWordId){
return dis[endWordId] / 2 + 1;
}
for(int &it: edge[x]){
if(dis[it] == INT_MAX){
dis[it] = dis[x] + 1;
que.push(it);
}
}
}
return 0;
}
};
class Solution {
Map<String, Integer> wordId = new HashMap<String, Integer>();
List<List<Integer>> edge = new ArrayList<List<Integer>>();
int nodeNum = 0;
public int ladderLength(String beginWord, String endWord, List<String> wordList) {
for (String word : wordList) {
addEdge(word);
}
addEdge(beginWord);
if (!wordId.containsKey(endWord)) {
return 0;
}
int[] dis = new int[nodeNum];
Arrays.fill(dis, Integer.MAX_VALUE);
int beginId = wordId.get(beginWord), endId = wordId.get(endWord);
dis[beginId] = 0;
Queue<Integer> que = new LinkedList<Integer>();
que.offer(beginId);
while (!que.isEmpty()) {
int x = que.poll();
if (x == endId) {
return dis[endId] / 2 + 1;
}
for (int it : edge.get(x)) {
if (dis[it] == Integer.MAX_VALUE) {
dis[it] = dis[x] + 1;
que.offer(it);
}
}
}
return 0;
}
public void addEdge(String word) {
addWord(word);
int id1 = wordId.get(word);
char[] array = word.toCharArray();
int length = array.length;
for (int i = 0; i < length; ++i) {
char tmp = array[i];
array[i] = '*';
String newWord = new String(array);
addWord(newWord);
int id2 = wordId.get(newWord);
edge.get(id1).add(id2);
edge.get(id2).add(id1);
array[i] = tmp;
}
}
public void addWord(String word) {
if (!wordId.containsKey(word)) {
wordId.put(word, nodeNum++);
edge.add(new ArrayList<Integer>());
}
}
}
Arrays.fill(dis, Integer.MAX_VALUE); 是 Java 中用于填充数组的静态方法。具体来说,它将数组 dis 中的所有元素设置为指定的值 Integer.MAX_VALUE。以下是详细的解释:
详细解释
-
Arrays类:Arrays是 Java 标准库中的一个实用工具类,提供了许多用于操作数组的方法。- 位于
java.util包中,因此在使用之前需要导入该包:import java.util.Arrays;
-
fill方法:fill方法用于将数组中的所有元素设置为指定的值。- 有多种重载形式,可以用于不同类型的数组(如
int[],double[],Object[]等)。
-
Arrays.fill(dis, Integer.MAX_VALUE);:dis是一个数组(通常是int[]类型)。Integer.MAX_VALUE是一个常量,表示int类型的最大值,即2^31 - 1(即2147483647)。- 该方法将
dis数组中的每一个元素都设置为Integer.MAX_VALUE。
示例代码
以下是一个完整的示例,展示了如何使用 Arrays.fill 方法来初始化一个距离数组 dis:
import java.util.Arrays;
public class WordLadder {
public static void main(String[] args) {
int n = 5; // 假设数组长度为 5
int[] dis = new int[n];
// 将 dis 数组中的所有元素设置为 Integer.MAX_VALUE
Arrays.fill(dis, Integer.MAX_VALUE);
// 打印数组以验证
System.out.println(Arrays.toString(dis));
}
}
输出
[2147483647, 2147483647, 2147483647, 2147483647, 2147483647]
使用场景
在图算法(如 Dijkstra 算法)中,dis 数组通常用于存储从起点到各个节点的最短距离。初始化为 Integer.MAX_VALUE 表示所有节点初始时距离起点都是无穷大,只有在找到路径时才会更新这些距离。
总结
Arrays.fill(dis, Integer.MAX_VALUE);:- 将数组
dis中的所有元素设置为Integer.MAX_VALUE。 - 用于初始化数组,通常在图算法中表示初始距离为无穷大。
- 将数组
通过这种方式,您可以方便地初始化数组,确保在后续计算中能够正确地更新和比较距离。
Arrays 类在 Java 中提供了许多实用的方法来操作数组。以下是一些常用的方法及其解释和示例:
常用方法
-
fill:- 将数组中的所有元素设置为指定的值。
- 示例:
int[] arr = new int[5]; Arrays.fill(arr, 10); System.out.println(Arrays.toString(arr)); // 输出: [10, 10, 10, 10, 10]
-
copyOf:- 复制指定数组的副本。
- 示例:
int[] original = {1, 2, 3, 4, 5}; int[] copy = Arrays.copyOf(original, original.length); System.out.println(Arrays.toString(copy)); // 输出: [1, 2, 3, 4, 5]
-
copyOfRange:- 复制指定数组的指定范围。
- 示例:
int[] original = {1, 2, 3, 4, 5}; int[] copyRange = Arrays.copyOfRange(original, 1, 4); System.out.println(Arrays.toString(copyRange)); // 输出: [2, 3, 4]
-
equals:- 比较两个数组是否相等。
- 示例:
int[] arr1 = {1, 2, 3}; int[] arr2 = {1, 2, 3}; System.out.println(Arrays.equals(arr1, arr2)); // 输出: true
-
deepEquals:- 比较两个多维数组是否相等。
- 示例:
int[][] arr1 = {{1, 2}, {3, 4}}; int[][] arr2 = {{1, 2}, {3, 4}}; System.out.println(Arrays.deepEquals(arr1, arr2)); // 输出: true
-
sort:- 对数组进行排序。
- 示例:
int[] arr = {5, 2, 8, 3, 1}; Arrays.sort(arr); System.out.println(Arrays.toString(arr)); // 输出: [1, 2, 3, 5, 8]
-
binarySearch:- 在排序数组中查找指定元素的索引。
- 示例:
int[] arr = {1, 2, 3, 5, 8}; int index = Arrays.binarySearch(arr, 3); System.out.println(index); // 输出: 2
-
toString:- 将数组转换为字符串表示。
- 示例:
int[] arr = {1, 2, 3, 4, 5}; System.out.println(Arrays.toString(arr)); // 输出: [1, 2, 3, 4, 5]
-
asList:- 将数组转换为固定大小的列表。
- 示例:
Integer[] arr = {1, 2, 3, 4, 5}; List<Integer> list = Arrays.asList(arr); System.out.println(list); // 输出: [1, 2, 3, 4, 5]
-
setAll:- 使用提供的生成器函数设置数组的所有元素。
- 示例:
int[] arr = new int[5]; Arrays.setAll(arr, i -> i * 2); System.out.println(Arrays.toString(arr)); // 输出: [0, 2, 4, 6, 8]
-
parallelSort:- 并行排序数组,适用于大型数组以提高性能。
- 示例:
int[] arr = {5, 2, 8, 3, 1}; Arrays.parallelSort(arr); System.out.println(Arrays.toString(arr)); // 输出: [1, 2, 3, 5, 8]
示例代码
以下是一个综合示例,展示了 Arrays 类中的一些常用方法:
import java.util.Arrays;
import java.util.List;
public class ArraysExample {
public static void main(String[] args) {
// 创建一个数组
int[] arr = {5, 2, 8, 3, 1};
// 填充数组
Arrays.fill(arr, 0);
System.out.println("Filled array: " + Arrays.toString(arr)); // 输出: Filled array: [0, 0, 0, 0, 0]
// 复制数组
int[] copy = Arrays.copyOf(arr, arr.length);
System.out.println("Copied array: " + Arrays.toString(copy)); // 输出: Copied array: [0, 0, 0, 0, 0]
// 复制指定范围
int[] copyRange = Arrays.copyOfRange(arr, 1, 4);
System.out.println("Copied range: " + Arrays.toString(copyRange)); // 输出: Copied range: [0, 0, 0]
// 排序数组
Arrays.sort(arr);
System.out.println("Sorted array: " + Arrays.toString(arr)); // 输出: Sorted array: [0, 0, 0, 0, 0]
// 二分查找
int index = Arrays.binarySearch(arr, 0);
System.out.println("Index of 0: " + index); // 输出: Index of 0: 0
// 转换为字符串
String arrStr = Arrays.toString(arr);
System.out.println("Array as string: " + arrStr); // 输出: Array as string: [0, 0, 0, 0, 0]
// 转换为列表
Integer[] arrObj = {1, 2, 3, 4, 5};
List<Integer> list = Arrays.asList(arrObj);
System.out.println("Array as list: " + list); // 输出: Array as list: [1, 2, 3, 4, 5]
// 使用生成器函数设置数组
Arrays.setAll(arr, i -> i * 2);
System.out.println("Set all with generator: " + Arrays.toString(arr)); // 输出: Set all with generator: [0, 2, 4, 6, 8]
// 并行排序
Arrays.parallelSort(arr);
System.out.println("Parallel sorted array: " + Arrays.toString(arr)); // 输出: Parallel sorted array: [0, 2, 4, 6, 8]
}
}
总结
Arrays类:- 提供了许多实用方法来操作数组。
- 常用方法包括
fill,copyOf,copyOfRange,equals,deepEquals,sort,binarySearch,toString,asList,setAll, 和parallelSort。
通过使用这些方法,您可以更高效地处理数组,简化代码并提高性能。
浙公网安备 33010602011771号