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。以下是详细的解释:

详细解释

  1. Arrays:

    • Arrays 是 Java 标准库中的一个实用工具类,提供了许多用于操作数组的方法。
    • 位于 java.util 包中,因此在使用之前需要导入该包:
      import java.util.Arrays;
      
  2. fill 方法:

    • fill 方法用于将数组中的所有元素设置为指定的值。
    • 有多种重载形式,可以用于不同类型的数组(如 int[], double[], Object[] 等)。
  3. 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 中提供了许多实用的方法来操作数组。以下是一些常用的方法及其解释和示例:

常用方法

  1. fill:

    • 将数组中的所有元素设置为指定的值。
    • 示例:
      int[] arr = new int[5];
      Arrays.fill(arr, 10);
      System.out.println(Arrays.toString(arr)); // 输出: [10, 10, 10, 10, 10]
      
  2. 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]
      
  3. copyOfRange:

    • 复制指定数组的指定范围。
    • 示例:
      int[] original = {1, 2, 3, 4, 5};
      int[] copyRange = Arrays.copyOfRange(original, 1, 4);
      System.out.println(Arrays.toString(copyRange)); // 输出: [2, 3, 4]
      
  4. equals:

    • 比较两个数组是否相等。
    • 示例:
      int[] arr1 = {1, 2, 3};
      int[] arr2 = {1, 2, 3};
      System.out.println(Arrays.equals(arr1, arr2)); // 输出: true
      
  5. deepEquals:

    • 比较两个多维数组是否相等。
    • 示例:
      int[][] arr1 = {{1, 2}, {3, 4}};
      int[][] arr2 = {{1, 2}, {3, 4}};
      System.out.println(Arrays.deepEquals(arr1, arr2)); // 输出: true
      
  6. sort:

    • 对数组进行排序。
    • 示例:
      int[] arr = {5, 2, 8, 3, 1};
      Arrays.sort(arr);
      System.out.println(Arrays.toString(arr)); // 输出: [1, 2, 3, 5, 8]
      
  7. binarySearch:

    • 在排序数组中查找指定元素的索引。
    • 示例:
      int[] arr = {1, 2, 3, 5, 8};
      int index = Arrays.binarySearch(arr, 3);
      System.out.println(index); // 输出: 2
      
  8. toString:

    • 将数组转换为字符串表示。
    • 示例:
      int[] arr = {1, 2, 3, 4, 5};
      System.out.println(Arrays.toString(arr)); // 输出: [1, 2, 3, 4, 5]
      
  9. asList:

    • 将数组转换为固定大小的列表。
    • 示例:
      Integer[] arr = {1, 2, 3, 4, 5};
      List<Integer> list = Arrays.asList(arr);
      System.out.println(list); // 输出: [1, 2, 3, 4, 5]
      
  10. setAll:

    • 使用提供的生成器函数设置数组的所有元素。
    • 示例:
      int[] arr = new int[5];
      Arrays.setAll(arr, i -> i * 2);
      System.out.println(Arrays.toString(arr)); // 输出: [0, 2, 4, 6, 8]
      
  11. 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

通过使用这些方法,您可以更高效地处理数组,简化代码并提高性能。

posted on 2025-02-18 11:47  爱吐水的小火龙  阅读(35)  评论(0)    收藏  举报