代码随想录打卡Day22、23、24、25

题目描述

  1. 组合(力扣中等难度)

给定两个整数 'n' 和 'k',返回范围 '[1, n]' 中所有可能的 'k' 个数的组合。可以按任何顺序返回答案。

解答代码

cpp 复制代码
class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;   // 用来存放符合条件的结果 
    void backtracking(int n, int k, int startIndex) {
        if (path.size() == k) {
            result.push_back(path);
            return;
        }    

        for (int i = startIndex; i <= n; i++) {
            path.push_back(i);
            backtracking(n, k, i + 1);
            path.pop_back();
        }
    }

    vector<vector<int>> combine(int n, int k) {
        result.clear();
        path.clear();
        backtracking(n, k, 1);
        return result;
    }
};

代码逻辑

  1. 定义两个成员变量:'result' 用于存放所有符合条件的组合结果,'path' 用于存放当前正在构造的组合路径。

  2. 在 'combine' 函数中初始化 'result' 和 'path',然后调用 'backtracking' 函数开始搜索。

  3. 'backtracking' 函数的具体流程如下:

  • 如果 'path' 的长度等于 'k',则说明找到了一个满足条件的组合,将 'path' 加入到 'result' 中。

  • 否则,从 'startIndex' 开始到 'n' 遍历每个数字 'i'。

  • 将当前数字 'i' 加入到 'path' 中,递归调用 'backtracking' 函数,并将起始位置 'startIndex' 更新为 'i + 1' 以避免重复数字。

  • 回溯操作:从递归返回后,将当前加入的数字 'i' 从 'path' 中移除,以便尝试新的组合路径。

代码难点

  1. 回溯与路径管理:回溯的关键在于通过路径添加和移除操作来维护当前组合状态。每次在 'path' 中添加一个新数字后,需要递归处理,递归完成后再回退一步,以保证 'path' 状态正确。

  2. 避免重复:在 'backtracking' 函数中,'for' 循环起始于 'startIndex',通过递增 'i' 保证每次组合中的元素不重复,也确保了不再包含之前的数字,避免了不必要的重复组合。

  3. 时间复杂度:组合问题的复杂度相对较高,因为每个数字组合都需要遍历和构造。

题目描述:

  1. 组合总和 III(力扣中等难度)

找出所有相加之和为 'n' 的 'k' 个数的组合,且满足以下条件:

  1. 只使用数字 1 到 9

  2. 每个数字最多使用一次

返回所有可能的有效组合的列表。列表中的组合可以按任意顺序返回,且不能包含重复组合。

解答代码:

cpp 复制代码
class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;

    void backtracking(int targetSum,int k, int sum, int startIndex) {
         
        if (sum > targetSum) return;

        if (path.size() == k) {
            if (sum == targetSum) {
                result.push_back(path);
                return;
            }
        }

        // 剪枝
        for (int i = startIndex; i <= 9 - (k - path.size()) + 1; i++) {
            sum += i;
            path.push_back(i);
            backtracking(targetSum, k, sum, i + 1);

            // 回溯
            sum -= i;
            path.pop_back();
        }
    }

    vector<vector<int>> combinationSum3(int k, int n) {
        result.clear(); // 可以不加
        path.clear();   // 可以不加
        backtracking(n, k, 0, 1);
        return result;
    }
};

代码逻辑:

  1. 在 'combinationSum3' 函数中初始化 'result' 和 'path',然后调用 'backtracking' 函数开始搜索组合

  2. 'backtracking' 函数的主要流程如下:

  • 首先判断当前和 'sum' 是否大于目标和 'targetSum',如果是则立即返回(剪枝)

  • 如果当前组合的长度等于 'k',则进一步判断 'sum' 是否等于 'targetSum',如果相等,将当前组合 'path' 添加到 'result' 中

  • 否则,从 'startIndex' 开始到 '9 - (k - path.size()) + 1' 遍历每个数字 'i'。'9 - (k - path.size()) + 1' 是一种剪枝方式,确保剩余的数字数量足够完成组合

  • 将当前数字 'i' 加入 'path',递归调用 'backtracking' 函数继续构建组合

  • 递归返回后进行回溯,将当前数字从 'sum' 和 'path' 中移除,尝试其他可能的组合路径

代码难点:

  1. 剪枝:在 'for' 循环中,通过 '9 - (k - path.size()) + 1' 来限制循环范围,可以有效减少不必要的搜索

  2. 条件判断顺序:先判断 'sum > targetSum' 可以避免不必要的递归

  3. 回溯:在递归中每次加入新的数字 'i' 后,需要在返回时将其移出,以保证路径状态

题目描述:

  1. 电话号码的字母组合(力扣中等难度)

给定一个仅包含数字 '2-9' 的字符串,返回所有它能表示的字母组合。答案可以按任意顺序返回。数字到字母的映射如下(与电话按键相同):

解答代码:

cpp 复制代码
class Solution {
public:
    vector<string> result;
    string s;
    const string letterMap[10] = {
        "", // 0
        "", // 1
        "abc", // 2
        "def", // 3
        "ghi", // 4
        "jkl", // 5
        "mno", // 6
        "pqrs", // 7
        "tuv", // 8
        "wxyz", // 9
    };

    void backtracking(const string& digits, int index) {
        if (index == digits.size()) {
            result.push_back(s);
            return;
        }

        int digit = digits[index] - '0';
        string letters = letterMap[digit];

        for (int i = 0; i < letters.size(); i++) {
            s.push_back(letters[i]);

            // 为什么是index + 1
            backtracking(digits, index + 1);
            s.pop_back();
        }
    }
    vector<string> letterCombinations(string digits) {
        s.clear();
        result.clear();
        if (digits.size() == 0) {
            return result;
        }
        backtracking(digits, 0);
        return result;
    }
};

代码逻辑:

  1. 'letterCombinations' 函数用于初始化结果和中间字符串 's',并在 'digits' 为空时直接返回空结果

  2. 'backtracking' 函数主要负责递归生成所有字母组合路径

  • 当 'index' 等于 'digits' 长度时,说明已生成一条完整的字母组合,将当前字符串 's' 加入 'result'

  • 否则,找到当前数字对应的字母字符串 'letters',并通过 'for' 循环依次添加每个字母到 's'

  • 对每个字母递归调用 'backtracking',并在递归返回后将 's' 中的最后一个字母移除(回溯)

代码难点:

  1. index + 1 的使用:每次递归时通过 'index + 1' 来处理下一个数字,以确保每个位置都能对应正确的字母组合

  2. 递归与回溯:递归过程中 's.push_back()' 和 's.pop_back()' 的配合确保了路径正确

题目描述:

  1. 组合总和(力扣中等难度)

给你一个无重复元素的整数数组 'candidates' 和一个目标整数 'target',找出 'candidates' 中所有和为 'target' 的不同组合,并以列表形式返回。'candidates' 中的同一个数字可以无限次重复被选取。如果至少有一个数字的使用次数不同,则视为不同的组合。

解答代码:

cpp 复制代码
class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;
 
    void backtracking(vector<int>& candidates, int sum, int target, int startIndex) {
        if (sum > target) {
            return;
        }

        if (sum == target) {
            result.push_back(path);
            return;
        }

        for (int i = startIndex; i < candidates.size(); i++) {
            path.push_back(candidates[i]);
            sum += candidates[i];
            backtracking(candidates, sum, target, i);
            sum -= candidates[i];
            path.pop_back();
        }
    }

    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        result.clear();
        path.clear();
        backtracking(candidates, 0, target, 0);
        return result;
    }
};

代码逻辑:

  1. 'combinationSum' 函数首先清空 'result' 和 'path',然后调用 'backtracking' 函数开始搜索

  2. 'backtracking' 函数的流程如下:

  • 若当前和 'sum' 超过 'target',直接返回(剪枝操作,减少不必要的递归)

  • 若当前和 'sum' 等于 'target',将 'path' 作为有效组合添加到 'result'

  • 否则,从 'startIndex' 开始遍历 'candidates' 数组

  • 将 'candidates[i]' 加入 'path' 并更新 'sum'

  • 递归调用 'backtracking',传入当前索引 'i' 以允许重复选择当前数字

  • 递归返回后执行回溯操作,移除 'path' 的最后一个元素并更新 'sum'

代码难点:

  1. 允许重复选择:递归调用时将当前索引 'i' 传入 'backtracking',使得后续递归仍能选择当前数字,从而实现重复选择

  2. 剪枝:当 'sum' 大于 'target' 时立即返回,避免不必要的计算

题目描述:

  1. 组合总和 II(力扣中等难度)

给定一个候选人编号的集合 `candidates` 和一个目标数 `target`,找出 `candidates` 中所有和为 `target` 的组合。`candidates` 中的每个数字在每个组合中只能使用一次。

解答代码:

cpp 复制代码
class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;
    void backtracking(vector<int>& candidates, int sum, int target, int startIndex, vector<bool>& used) {
        if (sum > target) return;
        if (sum == target) {
            result.push_back(path);
            return;
        }

        for (int i = startIndex; i < candidates.size(); i++) {
            if (i > 0 && candidates[i - 1] == candidates[i] && used[i - 1] == false) {
                continue;
            }
            sum += candidates[i];
            path.push_back(candidates[i]);
            used[i] = true;

            backtracking(candidates, sum, target, i + 1, used);

            // 回溯
            sum -= candidates[i];
            path.pop_back();
            used[i] = false;

        }
    }



    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        sort(candidates.begin(), candidates.end());
        vector<bool> used(candidates.size(), false);
        result.clear();
        path.clear();
        backtracking(candidates, 0, target, 0, used);
        return result;
    }
};

代码逻辑:

  1. 在 `combinationSum2` 函数中,首先对 `candidates` 数组进行排序,以便处理重复数字,并初始化 `used` 数组、`result` 和 `path`

  2. `backtracking` 函数的流程如下:

  • 如果当前和 `sum` 超过 `target`,立即返回

  • 如果当前和 `sum` 等于 `target`,将 `path` 作为有效组合添加到 `result`

  • 否则,从 `startIndex` 开始遍历 `candidates` 数组

  • 为了避免重复组合,如果 `candidates[i]` 和前一个数字相同,并且前一个数字未被使用,则跳过该数字

  • 将 `candidates[i]` 加入 `path` 并更新 `sum`,同时将 `used[i]` 标记为 `true`

  • 递归调用 `backtracking`,传入 `i + 1` 以确保每个数字只能使用一次

  • 递归返回后执行回溯操作,移除 `path` 中的最后一个元素并更新 `sum`,同时将 `used[i]` 重置为 `false`

代码难点:

  1. 去重处理:排序后通过判断 `candidates[i]` 是否等于前一个数字,并检查前一个数字是否已被使用,避免了相同数字在同一层重复使用,确保组合唯一

  2. 递归与回溯:使用 `used` 数组跟踪元素使用情况,配合回溯操作确保组合路径状态

题目描述:

  1. 分割回文串(力扣中等难度)

给定一个字符串 's',请将 's' 分割成一些子串,使每个子串都是回文串,返回所有可能的分割方案。

解答代码:

cpp 复制代码
class Solution {
public:
    vector<vector<string>> result;
    vector<string> path;
    void backtracking(const string& s, int startIndex) {
        if (startIndex == s.size()) {
            result.push_back(path);
            return;
        }

        for (int i = startIndex; i < s.size(); i++) {
            if (isPalindrome(s, startIndex, i))
            {
                string str = s.substr(startIndex, i - startIndex + 1);
                path.push_back(str);
            }
            else {
                continue;
            }
            backtracking(s, i + 1);
            path.pop_back();
        }

    }

    bool isPalindrome(const string& s, int start, int end) {
        while(start <= end) {
            if (s[start] != s[end]) {
                return false;
            }
            start++;
            end--;
        }
        return true;
    }

    vector<vector<string>> partition(string s) {
        result.clear();
        path.clear();
        backtracking(s, 0);
        return result;
    }
};

代码逻辑:

  1. 'partition' 函数初始化 'result' 和 'path',然后调用 'backtracking' 函数开始搜索

  2. 'backtracking' 函数的流程如下:

  • 如果 'startIndex' 等于字符串 's' 的长度,说明已到达字符串末尾,将 'path' 作为一个分割方案添加到 'result'

  • 否则,从 'startIndex' 到字符串末尾遍历子串

  • 对于每个子串,若 'isPalindrome' 判断为回文,则将该子串添加到 'path'

  • 递归调用 'backtracking',起始位置设为 'i + 1',尝试进一步分割

  • 递归返回后进行回溯操作,移除 'path' 中的最后一个子串,恢复当前路径状态

代码难点:

  1. 判断回文子串:通过 'isPalindrome' 函数判断 's[start]' 到 's[end]' 是否为回文,保证每个分割的子串都是回文

  2. 递归与回溯:'path.push_back' 和 'path.pop_back' 操作确保在每个递归层中保持路径的正确性

题目描述:

  1. 复原 IP 地址(力扣中等难度)

有效 IP 地址由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0)构成,整数之间用 '.' 分隔。给定一个只包含数字的字符串 `s`,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 `s` 中插入 '.' 来形成。你不能重新排序或删除 `s` 中的任何数字。你可以按任意顺序返回答案。

解答代码:

cpp 复制代码
class Solution {
public:
    vector<string> result;

    void backtracking(string& s, int startIndex, int pointNum) {
        if (pointNum == 3) {
            // 判断第四个字串
            if (isValid(s, startIndex, s.size() - 1)) {
                result.push_back(s);
            } 
            return;
        }

        for (int i = startIndex; i < s.size(); i++) {
            if (isValid(s, startIndex, i)) {
                s.insert(s.begin() + i + 1, '.');
                pointNum++;
                backtracking(s, i + 2, pointNum);

                // 回溯
                pointNum--;
                s.erase(s.begin() + i + 1);
            }
        }
    }

    bool isValid(const string& s, int start, int end) {
        if (start > end) {
            return false;
        }
        if (s[start] == '0' && start != end) {  // 0开头的不合法
            return false;
        }
        int num = 0;
        for (int i = start; i <= end ; i++) {
            if (s[i] > '9' || s[i] < '0') {
                return false;
            }
            num = num * 10 + (s[i] - '0');
            if (num > 255) {
                return false;
            }
        }
        return true;
    }

    vector<string> restoreIpAddresses(string s) {
        result.clear();
        if (s.size() < 4 || s.size() > 12) return result; // 算是剪枝了
        backtracking(s, 0, 0);
        return result;
    }
};

代码逻辑:

  1. `restoreIpAddresses` 函数会首先检查字符串 `s` 的长度是否在 4 到 12 之间。如果不满足条件,则返回空结果(剪枝)。

  2. `backtracking` 函数的流程如下:

  • 若 `pointNum` 为 3,表示已经插入了 3 个点,检查剩余部分是否为一个有效的 IP 地址段。如果有效,加入结果 `result`。

  • 否则,从 `startIndex` 开始遍历每个子串,检查子串是否符合 IP 地址段的有效性(使用 `isValid` 函数)。

  • 如果有效,插入一个点,然后递归调用 `backtracking` 继续处理后面的部分。

  • 回溯时移除插入的点,恢复状态。

  1. `isValid` 函数检查字符串是否符合一个有效的 IP 地址段:
  • 若字符串的第一个字符为 `0` 且长度大于 1,则无效(不能有前导零)。

  • 若转换为整数后大于 255,则无效。

  • 如果没有上述问题,则返回有效。

代码难点:

  1. 回溯与回溯路径管理:通过递归和回溯插入 `.`,并在回溯时恢复状态,确保不会重复计算。

  2. IP 地址的合法性验证:需要判断子串是否满足 IP 地址段的有效性(范围 0-255,不能有前导零)。

题目描述:

  1. 子集(力扣中等难度)

给定一个整数数组 `nums`,数组中的元素互不相同。返回该数组所有可能的子集(幂集)。解集不能包含重复的子集,你可以按任意顺序返回解集。

解答代码:

cpp 复制代码
class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;

    void backtracking(vector<int>& nums, int startIndex) {
        result.push_back(path);
        
        if (startIndex >= nums.size()) {
            return;
        }

        for (int i = startIndex; i < nums.size(); i++) {
            path.push_back(nums[i]);
            backtracking(nums, i + 1);
            path.pop_back();
        }
    }

    vector<vector<int>> subsets(vector<int>& nums) {
        result.clear();
        path.clear();
        backtracking(nums, 0);
        return result;
    }
};

代码逻辑:

  1. 在 `subsets` 函数中,初始化结果 `result` 和路径 `path`,然后调用 `backtracking` 函数进行递归搜索。

  2. `backtracking` 函数:

  • 每次递归都会将当前的路径 `path` 加入到结果 `result` 中。

  • 通过 `startIndex` 来控制递归的起始位置,确保不会重复包含子集中的元素。

  • 在每一层递归中,遍历当前索引 `startIndex` 到数组末尾的元素,将元素加入路径 `path` 中,并递归进入下一层。

  • 回溯时,使用 `path.pop_back()` 恢复路径状态,保证遍历到每个可能的子集。

  1. 最终,`result` 中保存了所有可能的子集。

代码难点:

  1. 回溯的深度控制:通过 `startIndex` 确保每个元素在子集中只能出现一次,避免重复的子集。

  2. 子集的生成:每一次递归都生成一个新的子集并加入结果中,这保证了幂集中的所有可能子集被遍历到。

题目描述:

  1. 子集(力扣中等难度)

给定一个整数数组 `nums`,数组中的元素互不相同。返回该数组所有可能的子集(幂集)。解集不能包含重复的子集,你可以按任意顺序返回解集。

解答代码:

cpp 复制代码
class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;

    void backtracking(vector<int>& nums, vector<bool>& used, int startIndex) {
        result.push_back(path);
        
        if (startIndex >= nums.size()) {
            return;
        }

        for (int i = startIndex; i < nums.size(); i++) {
            // used[i - 1] == true,说明同一树枝candidates[i - 1]使用过
            // used[i - 1] == false,说明同一树层candidates[i - 1]使用过
            // 而我们要对同一树层使用过的元素进行跳过
            if (i > 0 && nums[i - 1] == nums[i] && used[i - 1] == false) continue;
            path.push_back(nums[i]);
            used[i] = true;
            backtracking(nums, used, i + 1);
            path.pop_back();
            used[i] = false;
        }
    }

    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
        result.clear();
        path.clear();
        vector<bool> used(nums.size(), false);

        // 排序
        sort(nums.begin(), nums.end());
        backtracking(nums, used, 0);
        return result;
    }
};

代码逻辑:

  1. 在 `subsets` 函数中,初始化结果 `result` 和路径 `path`,然后调用 `backtracking` 函数进行递归搜索。

  2. `backtracking` 函数:

  • 每次递归都会将当前的路径 `path` 加入到结果 `result` 中。

  • 通过 `startIndex` 来控制递归的起始位置,确保不会重复包含子集中的元素。

  • 在每一层递归中,遍历当前索引 `startIndex` 到数组末尾的元素,将元素加入路径 `path` 中,并递归进入下一层。

  • 回溯时,使用 `path.pop_back()` 恢复路径状态,保证遍历到每个可能的子集。

  1. 最终,`result` 中保存了所有可能的子集。

代码难点:

  1. 回溯的深度控制:通过 `startIndex` 确保每个元素在子集中只能出现一次,避免重复的子集。

  2. 子集的生成:每一次递归都生成一个新的子集并加入结果中,这保证了幂集中的所有可能子集被遍历到。

题目描述:

  1. 子集 II(力扣中等难度)

给定一个整数数组 `nums`,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。解集不能包含重复的子集。返回的解集中,子集可以按任意顺序排列。

解答代码:

cpp 复制代码
class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;

    void backtracking(vector<int>& nums, int startIndex) {
        if (path.size() > 1)
            result.push_back(path);

        // uset的作用是对本层去重
        unordered_set<int> uset;

        for (int i = startIndex; i < nums.size(); i++) {

            // ?
            if ((!path.empty() && nums[i] < path.back()) ||
                uset.find(nums[i]) != uset.end()) {
                continue;
            }

            // 数层去重,每次递归都会定义新的uset,故不需要回溯
            uset.insert(nums[i]);
            path.push_back(nums[i]);
            backtracking(nums, i + 1);
            path.pop_back();
        }
    }
    vector<vector<int>> findSubsequences(vector<int>& nums) {
        result.clear();
        path.clear();
        backtracking(nums, 0);
        return result;
    }
};

```

代码逻辑:

  1. `subsetsWithDup` 函数会首先对输入数组 `nums` 进行排序。排序是为了方便跳过重复元素(确保同一层树中不会重复选取相同的元素)。

  2. `backtracking` 函数:

  • 每次递归都会将当前的路径 `path` 加入到结果 `result` 中。

  • 对于每个元素,在递归时检查是否可以使用该元素:

  • 如果当前元素 `nums[i]` 与前一个元素相同,并且前一个元素在同一树层已被跳过,则跳过当前元素,以避免重复子集。

  • 若当前元素可以使用,将其加入路径 `path`,并递归处理下一部分。

  • 回溯时移除路径中的最后一个元素,并恢复元素的使用状态 `used[i]`。

  1. 最终,`result` 中保存了所有不重复的子集。

代码难点:

  1. 跳过重复元素:通过排序和 `used` 数组来确保在同一树层中不会选择重复的元素,避免生成重复的子集。

  2. 回溯与状态恢复:使用 `path` 记录当前的子集,利用 `used` 数组进行元素的使用状态控制,确保在递归时不会重复选择相同的元素。

题目描述:

  1. 全排列(力扣中等难度)

给定一个不含重复数字的数组 `nums`,返回其所有可能的全排列。你可以按任意顺序返回答案。

解答代码:

cpp 复制代码
class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;

    void backtracking(vector<int>& nums, int startIndex) {
        if (path.size() > 1)
            result.push_back(path);

        // uset的作用是对本层去重
        unordered_set<int> uset;

        for (int i = startIndex; i < nums.size(); i++) {

            // ?
            if ((!path.empty() && nums[i] < path.back()) ||
                uset.find(nums[i]) != uset.end()) {
                continue;
            }

            // 数层去重,每次递归都会定义新的uset,故不需要回溯
            uset.insert(nums[i]);
            path.push_back(nums[i]);
            backtracking(nums, i + 1);
            path.pop_back();
        }
    }
    vector<vector<int>> findSubsequences(vector<int>& nums) {
        result.clear();
        path.clear();
        backtracking(nums, 0);
        return result;
    }
};

代码逻辑:

  1. `permute` 函数:
  • 用来启动回溯过程并返回最终的所有排列结果。初始化 `result` 和 `path` 并调用 `backtracking`。

  • 创建一个 `used` 数组,表示每个元素是否已被使用。

  1. `backtracking` 函数:
  • 递归地构建排列。当 `path` 中的元素个数等于 `nums` 的大小时,表示一个完整的排列已经生成,加入 `result`。

  • 遍历数组中的每个元素:

  • 如果元素已经被使用,则跳过。

  • 否则,加入当前元素到 `path`,标记为已使用,并继续递归调用 `backtracking`。

  • 回溯时,移除 `path` 中的最后一个元素,并恢复其在 `used` 数组中的状态。

  1. 最终返回的 `result` 包含了所有可能的排列。

代码难点:

  1. 回溯的状态管理:通过 `path` 记录当前排列,通过 `used` 数组来标记元素是否被选择,确保每个元素只会在排列中出现一次。

  2. 递归与回溯:递归逐层构建排列,每次回溯时通过 `pop_back()` 从 `path` 中移除元素,并恢复 `used` 数组中的状态,确保所有可能的排列都会被生成。

相关推荐
言之。1 小时前
【K-Means】
算法·机器学习·kmeans
hummhumm1 小时前
第 10 章 - Go语言字符串操作
java·后端·python·sql·算法·golang·database
Jeffrey_oWang1 小时前
软间隔支持向量机
算法·机器学习·支持向量机
算法歌者2 小时前
[算法]入门1.矩阵转置
算法
用户8134411823612 小时前
分布式训练
算法
林开落L2 小时前
前缀和算法习题篇(上)
c++·算法·leetcode
远望清一色2 小时前
基于MATLAB边缘检测博文
开发语言·算法·matlab
tyler_download2 小时前
手撸 chatgpt 大模型:简述 LLM 的架构,算法和训练流程
算法·chatgpt
SoraLuna3 小时前
「Mac玩转仓颉内测版7」入门篇7 - Cangjie控制结构(下)
算法·macos·动态规划·cangjie
我狠狠地刷刷刷刷刷3 小时前
中文分词模拟器
开发语言·python·算法