LeetCode 每周算法 6(图论、回溯)

LeetCode 每周算法 6(图论、回溯)

图论算法:

python 复制代码
class Solution:  
    def dfs(self, grid: List[List[str]], r: int, c: int) -> None:  
        """  
        深度优先搜索函数,用于遍历并标记与当前位置(r, c)相连的所有陆地
        (即值为"1"的格子)为已访问(即标记为0)。  
  
        :param grid: 二维网格,其中的每个元素都是'0'或'1'。  
        :param r: 当前遍历到的行索引。  
        :param c: 当前遍历到的列索引。  
        """  
        grid[r][c] = '0'  # 将当前位置标记为已访问(即陆地变为水)  
        nr, nc = len(grid), len(grid[0])  # 获取网格的行数和列数  
        # 遍历当前位置的上下左右四个相邻位置  
        for x, y in [(r - 1, c), (r + 1, c), (r, c - 1), (r, c + 1)]:  
            # 检查相邻位置是否在网格范围内且为陆地(即值为'1')  
            if 0 <= x < nr and 0 <= y < nc and grid[x][y] == "1":  
                self.dfs(grid, x, y)  # 递归地遍历相邻的陆地  
  
    def numIslands(self, grid: List[List[str]]) -> int:  
        """  
        计算给定网格中的岛屿数量。  
  
        :param grid: 二维网格,其中的每个元素都是'0'或'1'。  
        :return: 网格中的岛屿数量。  
        """  
        nr = len(grid)  
        if nr == 0:  # 如果网格为空,则岛屿数量为0  
            return 0  
        nc = len(grid[0])  # 获取网格的列数  
  
        num_islands = 0  # 初始化岛屿数量为0  
        for r in range(nr):  # 遍历网格的每一行  
            for c in range(nc):  # 遍历网格的每一列  
                if grid[r][c] == "1":  # 如果当前位置是陆地  
                    num_islands += 1  # 岛屿数量加1  
                    self.dfs(grid, r, c)  # 调用dfs函数遍历并标记与当前陆地相连的所有陆地  
  
        return num_islands  # 返回岛屿数量
python 复制代码
class Solution:  
    def orangesRotting(self, grid: List[List[int]]) -> int:  
        R, C = len(grid), len(grid[0])  # 获取网格的行数和列数  
  
        # 初始化一个队列,用于存放腐烂橙子(值为2)的位置及其腐烂时间(初始为0)  
        queue = deque()  
        for r, row in enumerate(grid):  
            for c, val in enumerate(row):  
                if val == 2:  
                    queue.append((r, c, 0))  
  
        # 定义一个辅助函数,用于生成当前橙子位置(r, c)的上下左右四个相邻位置  
        def neighbors(r, c):  
            for nr, nc in ((r - 1, c), (r, c - 1), (r + 1, c), (r, c + 1)):  
                if 0 <= nr < R and 0 <= nc < C:  # 确保相邻位置在网格范围内  
                    yield nr, nc  
  
        d = 0  # 初始化腐烂时间计数器  
        while queue:  # 当队列不为空时,继续执行  
            r, c, d = queue.popleft()  # 从队列中取出腐烂橙子的位置及其腐烂时间  
            for nr, nc in neighbors(r, c):  # 遍历当前腐烂橙子的四个相邻位置  
                if grid[nr][nc] == 1:  # 如果相邻位置是新鲜的橙子  
                    grid[nr][nc] = 2  # 将其标记为腐烂的橙子  
                    queue.append((nr, nc, d + 1))  # 将其加入队列,并更新腐烂时间为当前时间+1  
  
        # 检查网格中是否还有新鲜的橙子(值为1)  
        if any(1 in row for row in grid):  
            return -1  # 如果有,说明无法让所有橙子都腐烂,返回-1  
        return d  # 否则,返回最后的腐烂时间
python 复制代码
class Solution:  
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:  
        # 创建一个defaultdict来存储课程的邻接表,即每个课程的后继课程列表  
        edges = collections.defaultdict(list)  
        # 创建一个列表来存储每个课程的入度(即有多少课程是该课程的前置课程)  
        indeg = [0] * numCourses  
  
        # 遍历先决条件列表,构建邻接表和入度列表  
        for info in prerequisites:  
            # info[1] 是当前课程,info[0] 是其前置课程  
            # 将当前课程(info[1])的后继课程(info[0])添加到邻接表中  
            edges[info[1]].append(info[0])  
            # 将前置课程(info[0])的入度加1  
            indeg[info[0]] += 1  
  
        # 创建一个双端队列,用于存储入度为0的课程(即没有前置课程的课程)  
        q = collections.deque([u for u in range(numCourses) if indeg[u] == 0])  
        # 初始化已访问(或已完成)的课程数  
        visited = 0  
  
        # 使用广度优先搜索(BFS)遍历课程  
        while q:  
            # 每从队列中取出一个课程,表示该课程可以完成  
            visited += 1  
            u = q.popleft()  
            # 遍历当前课程的所有后继课程  
            for v in edges[u]:  
                # 将后继课程的入度减1,表示完成了一个前置课程  
                indeg[v] -= 1  
                # 如果后继课程的入度变为0,说明其所有前置课程都已完成,可以加入队列继续搜索  
                if indeg[v] == 0:  
                    q.append(v)  
          
        # 如果已访问的课程数等于总课程数,说明所有课程都可以完成  
        # 否则,存在环,无法完成所有课程  
        return visited == numCourses
python 复制代码
class Trie:  
    def __init__(self):  
        # 初始化Trie节点,children是一个长度为26的列表,
        # 用于存储指向子节点的引用(假设只处理小写字母a-z)  
        # 每个位置对应一个字母(例如,0对应'a',1对应'b',...,25对应'z')  
        # isEnd用于标记该节点是否是某个单词的结尾  
        self.children = [None] * 26  
        self.isEnd = False  
  
    def searchPrefix(self, prefix: str) -> "Trie":  
        # 搜索并返回给定前缀对应的最后一个Trie节点  
        # 如果前缀不存在于Trie中,则返回None  
        node = self  # 从根节点开始搜索  
        for ch in prefix:  
            # 将字符转换为对应的索引('a'->0, 'b'->1, ..., 'z'->25)  
            ch = ord(ch) - ord("a")  
            # 如果当前节点的children中对应字符的节点不存在,说明前缀不存在,返回None  
            if not node.children[ch]:  
                return None  
            # 否则,移动到子节点继续搜索  
            node = node.children[ch]  
        # 如果所有字符都成功匹配,返回最后一个节点  
        return node  
  
    def insert(self, word: str) -> None:  
        # 将一个单词插入到Trie中  
        node = self  # 从根节点开始插入  
        for ch in word:  
            # 将字符转换为对应的索引  
            ch = ord(ch) - ord("a")  
            # 如果当前节点的children中对应字符的节点不存在,则创建一个新的Trie节点  
            if not node.children[ch]:  
                node.children[ch] = Trie()  
            # 移动到子节点继续插入  
            node = node.children[ch]  
        # 标记最后一个节点为单词的结尾  
        node.isEnd = True  
  
    def search(self, word: str) -> bool:  
        # 搜索Trie中是否存在一个完整的单词  
        # 使用searchPrefix找到最后一个节点,然后检查该节点是否是某个单词的结尾  
        node = self.searchPrefix(word)  
        return node is not None and node.isEnd  
  
    def startsWith(self, prefix: str) -> bool:  
        # 检查Trie中是否存在以给定前缀开头的单词  
        # 使用searchPrefix找到最后一个节点,如果找到,则说明存在以该前缀开头的单词  
        return self.searchPrefix(prefix) is not None

# Your Trie object will be instantiated and called as such:
# obj = Trie()
# obj.insert(word)
# param_2 = obj.search(word)
# param_3 = obj.startsWith(prefix)

图论算法:

cpp 复制代码
class Solution {  
public:  
    // 回溯函数,用于生成所有排列  
    // res: 存储所有排列的二维向量  
    // output: 当前排列的向量,通过修改它来生成新的排列  
    // first: 当前需要确定位置的索引(从0开始)  
    // len: 输入数组nums的长度,即需要排列的元素总数  
    void backtrack(vector<vector<int>>& res, vector<int>& output, int first, int len) {  
        // 如果已经处理完所有元素(即已经填充了所有位置),则将当前排列添加到结果中
        if (first == len) {  
            // 使用emplace_back直接在res的末尾构造一个output的副本
            res.emplace_back(output);  
            return;  
        }  
        // 从first开始,遍历所有未确定位置的元素
        for (int i = first; i < len; ++i) {  
            // 将当前位置的元素与first位置的元素交换,
            // 这样可以尝试将不同的元素放在first位置  
            swap(output[i], output[first]);  
            // 递归地处理下一个位置(first+1)
            backtrack(res, output, first + 1, len);  
            // 回溯,撤销上一步的交换,以便尝试其他可能性
            swap(output[i], output[first]);  
        }  
    }  
  
    // 公开接口,用于生成给定数组nums的所有排列  
    // nums: 需要排列的整数数组  
    // 返回值: 包含所有排列的二维向量  
    vector<vector<int>> permute(vector<int>& nums) {  
        vector<vector<int>> res; // 初始化结果向量
        // 从第一个元素开始回溯,直到处理完所有元素    
        backtrack(res, nums, 0, (int)nums.size());
        return res; // 返回所有排列的集合  
    }  
};
cpp 复制代码
// 迭代法实现子集枚举
class Solution {  
public:  
    // 用于临时存储当前子集的结果  
    vector<int> output;  
    // 用于存储所有子集的结果  
    vector<vector<int>> ans;  
  
    // 生成给定整数数组nums的所有子集  
    vector<vector<int>> subsets(vector<int>& nums) {  
        // 遍历所有可能的位掩码,从0到2^nums.size() - 1  
        // 每个位掩码都代表一个子集,其中1表示选择该位置的元素,0表示不选择  
        for (int mask = 0; mask < (1 << nums.size()); ++mask) {  
            // 清空output,为构建新的子集做准备  
            output.clear();  
            // 遍历nums中的每个元素及其对应的位掩码位  
            for (int i = 0; i < nums.size(); ++i) {  
                // 如果mask的第i位是1(即mask & (1 << i)不为0),则将nums[i]加入当前子集  
                if (mask & (1 << i)) {  
                    output.push_back(nums[i]);  
                }  
            }  
            // 将构建好的子集添加到结果集中  
            ans.push_back(output);  
        }  
        // 返回包含所有子集的结果集  
        return ans;  
    }  
};

// 递归法实现子集枚举
// class Solution {  
// public:  
//     vector<int> output; // 用于临时存储当前子集的结果  
//     vector<vector<int>> ans; // 用于存储所有子集的结果  
  
//     // 回溯函数,从数组的第first个元素开始构建子集  
//     // first 表示当前正在处理的元素在nums中的索引  
//     // nums 是给定的整数数组  
//     void backtrack(int first, vector<int>& nums) {  
//         // 如果已经处理了nums中的所有元素,则将当前子集添加到结果集中  
//         if (first == nums.size()) {  
//             ans.push_back(output);  
//             return;  
//         }  
          
//         // 选择当前元素加入子集  
//         output.push_back(nums[first]);  
//         // 递归处理下一个元素,继续构建子集  
//         backtrack(first + 1, nums);  
          
//         // 回溯,撤销选择当前元素,尝试不包含当前元素的情况  
//         output.pop_back();  
//         backtrack(first + 1, nums); 
//     }  
  
//     // 主函数,用于生成nums的所有子集  
//     vector<vector<int>> subsets(vector<int>& nums) {  
//         backtrack(0, nums);  
//         return ans;  
//     }  
// }; 
cpp 复制代码
class Solution {  
public:  
    // 主函数,用于生成给定数字字符串的所有字母组合  
    vector<string> letterCombinations(string digits) {  
        if (digits.empty()) { // 如果输入的数字字符串为空,则直接返回空的组合列表  
            return combinations;  
        }  
        string combination; // 用于存储当前正在构建的字母组合  
        vector<string> combinations; // 存储所有可能的字母组合  
        // 创建一个哈希表,将数字映射到它们对应的字母字符串  
        unordered_map<char, string> phoneMap{  
            {'2', "abc"},  
            {'3', "def"},  
            {'4', "ghi"},  
            {'5', "jkl"},  
            {'6', "mno"},  
            {'7', "pqrs"},  
            {'8', "tuv"},  
            {'9', "wxyz"}  
        };  
        // 调用回溯函数来生成所有可能的组合  
        backtrack(combinations, phoneMap, digits, 0, combination);  
        return combinations; // 返回所有生成的字母组合  
    }  
  
    // 回溯函数,用于递归地生成所有可能的字母组合  
    void backtrack(vector<string>& combinations, const unordered_map<char, string>& phoneMap, const string& digits, int index, string& combination) {  
        if (index == digits.length()) { // 如果已经处理完所有数字,则将当前组合添加到结果列表中  
            combinations.push_back(combination);  
        } else {  
            char digit = digits[index]; // 获取当前正在处理的数字  
            const string& letters = phoneMap.at(digit); // 从哈希表中获取该数字对应的字母字符串  
            for (const char& letter: letters) { // 遍历该数字对应的所有字母  
                combination.push_back(letter); // 将当前字母添加到当前组合中  
                // 递归调用回溯函数,处理下一个数字,同时传入更新后的组合  
                backtrack(combinations, phoneMap, digits, index + 1, combination);  
                combination.pop_back(); // 回溯,撤销上一步的添加操作,以便尝试下一个字母  
            }  
        }  
    }  
};
cpp 复制代码
class Solution {  
public:  
    // 用于存储所有可能的组合结果的向量  
    vector<vector<int>> result;  
    // 用于在回溯过程中构建当前路径的向量  
    vector<int> path;  
  
    // 回溯函数,用于生成所有可能的组合  
    // candidates: 候选数字的集合  
    // target: 目标值,需要找到的和  
    // start: 从哪个候选数字开始考虑(避免重复使用相同的数字)  
    void backtrack(const vector<int>& candidates, int target, int start) {  
        // 如果当前目标和已经小于0,说明当前路径不可行,直接返回  
        if (target < 0) return;  
        // 如果目标和为0,说明找到了一个有效的组合,将其添加到结果中  
        if (target == 0) {  
            result.push_back(path);  
            return;  
        }  
        // 遍历候选数字,从start开始,确保不重复使用数字,并且当前数字不超过目标和  
        for (int i = start; i < candidates.size() && target - candidates[i] >= 0; i++) {  
            // 将当前数字添加到路径中  
            path.push_back(candidates[i]);  
            // 递归调用,目标值减去当前数字,start仍为i,因为可以重复使用相同的数字  
            // 注意:在某些问题中,可能需要将start改为i+1来避免重复使用相同的数字  
            backtrack(candidates, target - candidates[i], i);  
            // 回溯,撤销选择,继续尝试其他可能  
            path.pop_back();  
        }  
    }  
  
    // 主函数,用于找到所有可以使数字和为target的组合  
    // candidates: 候选数字的集合  
    // target: 目标值  
    // 返回值: 所有可能的组合  
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {  
        // 对候选数字进行排序,这有助于在回溯过程中剪枝,提高效率  
        // 特别是当允许重复使用数字时,排序可以确保较小的数字先被考虑  
        sort(candidates.begin(), candidates.end());  
        // 调用回溯函数开始搜索  
        backtrack(candidates, target, 0);  
        // 返回所有找到的组合  
        return result;  
    }  
};
cpp 复制代码
class Solution {  
    // 回溯函数,用于生成所有有效的括号组合  
    // result: 存储所有有效括号组合的字符串向量  
    // current: 当前正在构建的括号字符串  
    // left: 当前已使用的左括号数量  
    // right: 当前已使用的右括号数量  
    // n: 目标括号对的数量  
    void backtrack(vector<string>& result, string& current, int left, int right, int n) {  
        // 如果当前括号字符串的长度达到了目标长度(n对括号即2n个字符)  
        // 则将其添加到结果向量中  
        if (current.size() == n * 2) {  
            result.push_back(current);  
            return;  
        }  
        // 如果还可以添加左括号(即左括号数量小于n)  
        if (left < n) {  
            current.push_back('('); // 添加左括号  
            backtrack(result, current, left + 1, right, n); // 递归调用,左括号数量+1  
            current.pop_back(); // 回溯,撤销上一步的操作  
        }  
        // 如果右括号数量小于左括号数量(保证括号的有效性)  
        if (right < left) {  
            current.push_back(')'); // 添加右括号  
            backtrack(result, current, left, right + 1, n); // 递归调用,右括号数量+1  
            current.pop_back(); // 回溯,撤销上一步的操作  
        }  
    }  
  
public:  
    // 生成所有可能的、且有效的括号组合的公共接口  
    // n: 括号对的数量  
    vector<string> generateParenthesis(int n) {  
        vector<string> result; // 存储结果的向量  
        string current; // 当前正在构建的括号字符串  
        backtrack(result, current, 0, 0, n); // 从无括号开始,调用回溯函数  
        return result; // 返回所有有效的括号组合  
    }  
};

// class Solution {
//     bool valid(const string& str) {
//         int balance = 0;
//         for (char c: str) {
//             if (c == '(') {
//                 ++balance;
//             } else {
//                 --balance;
//             }
//             if (balance < 0) {
//                 return false;
//             }
//         }
//         return balance == 0;
//     }

//     void backtrack(string& current, int n, vector<string>& result) {
//         if (n == current.size()) {
//             if (valid(current)) {
//                 result.push_back(current);
//             }
//             return;
//         }
//         current += '(';
//         backtrack(current, n, result);
//         current.pop_back();
//         current += ')';
//         backtrack(current, n, result);
//         current.pop_back();
//     }
// public:
//     vector<string> generateParenthesis(int n) {
//         vector<string> result;
//         string current;
//         backtrack(current, n * 2, result);
//         return result;
//     }
// };
cpp 复制代码
class Solution {  
public:  
    // 判断给定单词是否可以通过在棋盘board上相邻位置上的字母连接而成  
    bool exist(vector<vector<char>>& board, string word) {  
        // 遍历棋盘上的每一个位置作为起始点  
        for (int i = 0; i < board.size(); i++) {  
            for (int j = 0; j < board[0].size(); j++) {  
                // 为每个起始点创建一个访问标记矩阵,初始都为false  
                vector<vector<bool>> visited(board.size(), vector<bool>(board[0].size(), false));  
                // 从当前位置开始,尝试深度优先搜索以找到单词  
                if (dfs(board, visited, word, 0, i, j)) return true; // 如果找到单词,则返回true  
            }  
        }  
  
        // 如果遍历完所有起始点都没有找到单词,则返回false  
        return false;  
    }  
  
private:  
    // 深度优先搜索函数,尝试在棋盘上找到单词  
    bool dfs(vector<vector<char>>& board, vector<vector<bool>>& visited, const string& word, int str_index, int i, int j) {  
        // 如果已经匹配完单词的所有字符,说明找到了单词,返回true  
        if (str_index == word.size()) return true;  
          
        // 检查当前位置是否越界、是否已访问过、或者是否与单词的当前字符不匹配  
        // 如果任何一个条件不满足,则无法继续搜索,返回false  
        if (i >= board.size() || i < 0 ||  
            j >= board[0].size() || j < 0 ||  
            visited[i][j] == true || board[i][j] != word[str_index]) return false;  
  
        // 标记当前位置为已访问  
        visited[i][j] = true;  
  
        // 尝试向上、下、左、右四个方向搜索  
        // 如果在任何一个方向上找到了单词,则返回true  
        if (dfs(board, visited, word, str_index + 1, i + 1, j) ||  // 向右  
            dfs(board, visited, word, str_index + 1, i - 1, j) ||  // 向左  
            dfs(board, visited, word, str_index + 1, i, j + 1) ||  // 向下  
            dfs(board, visited, word, str_index + 1, i, j - 1)) return true; // 向上  
  
        // 如果四个方向都没有找到单词,则回溯,将当前位置标记为未访问  
        visited[i][j] = false;  
  
        // 返回false,表示以当前位置为起始点没有找到单词  
        return false;  
    }  
};
cpp 复制代码
class Solution {  
private:  
    // f是一个二维动态数组,用于存储字符串s中任意子串[i, j]是否为回文串的布尔值  
    vector<vector<int>> dp;  
    // result是一个二维字符串向量,用于存储所有满足条件的分割结果,每个内部向量代表一种分割方式  
    vector<vector<string>> result;  
    // answer是一个字符串向量,用于在DFS过程中临时存储当前的分割结果  
    vector<string> answer;  
    // n表示字符串s的长度  
    int n;  
  
public:   
    // 深度优先搜索函数,用于遍历所有可能的分割方式  
    // s是当前处理的字符串,i是当前遍历到的起始位置  
    void dfs(const string& s, int i) {  
        // 如果遍历到了字符串的末尾,说明找到了一种分割方式,将其添加到结果中  
        if (i == n) {  
            result.push_back(answer);  
            return;  
        }  
        // 从当前位置i开始,尝试所有可能的分割点j  
        for (int j = i; j < n; ++j) {  
            // 如果子串[i, j]是回文串,则进行下一步分割  
            if (dp[i][j]) {  
                // 将当前回文子串添加到答案中  
                answer.push_back(s.substr(i, j - i + 1));  
                // 递归调用dfs,从j+1位置开始继续搜索  
                dfs(s, j + 1);  
                // 回溯,移除刚刚添加的回文子串,以尝试其他可能的分割  
                answer.pop_back();  
            }  
        }  
    }  
  
    // partition函数是类的公开接口,用于找到并返回所有满足条件的分割方式  
    vector<vector<string>> partition(string s) {  
        // 初始化n为字符串s的长度  
        n = s.size();  
        // 初始化f数组,默认所有子串都是回文串(之后会通过动态规划更新)  
        dp.assign(n, vector<int>(n, true));  
  
        // 使用动态规划计算f数组,即判断所有子串是否为回文串  
        for (int i = n - 1; i >= 0; --i) {  
            for (int j = i; j < n; ++j) {  
                // 如果首尾字符相等且去掉首尾后的子串也是回文串,则当前子串是回文串  
                dp[i][j] = (s[i] == s[j] && (j - i <= 1 || dp[i + 1][j - 1]));  
            }  
        }  
  
        // 从字符串的起始位置开始,使用深度优先搜索遍历所有可能的分割方式  
        dfs(s, 0);  
        // 返回所有满足条件的分割结果  
        return result;  
    }  
};
cpp 复制代码
class Solution {  
private:  
    // 用于存储所有有效的N皇后解决方案  
    vector<vector<string>> result;  
  
    // 回溯函数,尝试在每一行放置皇后,并递归地处理下一行  
    void backtracking(int n, int row, vector<string>& chessboard) {  
        // 如果已经处理完所有行,说明找到了一个有效的解决方案,将其添加到结果中  
        if (row == n) {  
            result.push_back(chessboard);  
            return;  
        }  
        // 遍历当前行的每一列  
        for (int col = 0; col < n; col++) {  
            // 检查在当前位置放置皇后是否有效  
            if (isvalid(row, col, chessboard, n)) {  
                // 在当前位置放置皇后  
                chessboard[row][col] = 'Q';  
                // 递归处理下一行  
                backtracking(n, row + 1, chessboard);  
                // 回溯,撤销在当前位置放置的皇后  
                chessboard[row][col] = '.';  
            }  
        }  
    }  
  
    // 检查在(row, col)位置放置皇后是否有效  
    // 有效的条件是当前位置所在列、左上方对角线、右上方对角线上没有皇后  
    bool isvalid(int row, int col, vector<string>& chessboard, int n) {  
        // 检查列上是否有皇后  
        for (int i = 0; i < row; i++) {  
            if (chessboard[i][col] == 'Q') {  
                return false;  
            }  
        }  
        // 检查左上方对角线上是否有皇后  
        for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {  
            if (chessboard[i][j] == 'Q') {  
                return false;  
            }  
        }  
        // 检查右上方对角线上是否有皇后  
        for (int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {  
            if (chessboard[i][j] == 'Q') {  
                return false;  
            }  
        }  
        // 如果没有冲突,则当前位置有效  
        return true;  
    }  
  
public:  
    // 主函数,用于解决N皇后问题  
    // 返回所有有效的N皇后解决方案  
    vector<vector<string>> solveNQueens(int n) {  
        // 清除之前的结果  
        result.clear();  
        // 初始化棋盘,所有位置都是'.'  
        vector<string> chessboard(n, string(n, '.'));  
        // 从第一行开始回溯  
        backtracking(n, 0, chessboard);  
        // 返回所有有效的解决方案  
        return result;  
    }  
};
相关推荐
Jasmine_llq19 分钟前
《 火星人 》
算法·青少年编程·c#
闻缺陷则喜何志丹29 分钟前
【C++动态规划 图论】3243. 新增道路查询后的最短距离 I|1567
c++·算法·动态规划·力扣·图论·最短路·路径
TENET信条39 分钟前
代码随想录 day52 第十一章 图论part03
图论
Lenyiin1 小时前
01.02、判定是否互为字符重排
算法·leetcode
鸽鸽程序猿1 小时前
【算法】【优选算法】宽搜(BFS)中队列的使用
算法·宽度优先·队列
Jackey_Song_Odd1 小时前
C语言 单向链表反转问题
c语言·数据结构·算法·链表
Watermelo6171 小时前
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
开发语言·前端·javascript·算法·数据挖掘·数据分析·ecmascript
乐之者v1 小时前
leetCode43.字符串相乘
java·数据结构·算法
A懿轩A2 小时前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组