Notas de cepillado de Leetcode (C++) - método de retroceso

Notas de cepillado de Leetcode (C++) - método de retroceso

Ordene las ideas en el proceso de repasar las preguntas, resúmalas y compártalas aquí.
dirección de github: https://github.com/lvjian0706/Leetcode-solutions
El proyecto de github se creó recientemente, y el código y las ideas se cargarán uno tras otro. El código está basado en C++ y python. Al mismo tiempo, el algoritmo de clasificación básico también se clasificará y cargará.

39. suma combinada

Dada una matriz de candidatos sin elementos repetidos y un objetivo numérico objetivo, descubra todas las combinaciones de candidatos que pueden hacer que la suma de números sea un objetivo.

Los números en candidatos se pueden seleccionar repetidamente sin límite.

Explicación:
Todos los números (incluido el destino) son números enteros positivos.
Un conjunto de soluciones no puede contener combinaciones duplicadas.

Ejemplo 1:
Entrada: candidatos = [2,3,6,7], objetivo = 7,
el conjunto de soluciones es:
[
[7],
[2,2,3]
]
Ejemplo 2:
Entrada: candidatos = [2,3 ,5], objetivo = 8,
el conjunto de soluciones es:
[
[2,2,2,2],
[2,3,3],
[3,5]
]

class Solution {
    
    
public:
    /*
    1. 当当前组合的和大于target时,直接return,等于target时,将组合push到最终答案中;
    2. 为了避免重复组合的情况,定义变量i用于记录当前遍历到了哪个元素,之前的元素不再重复遍历;
    3. 从第i个元素开始遍历,套用回溯算法模板,将当前元素push到组合中,sum加上当前元素,继续递归;
    4. 在组合中删除当前元素,sum减去当前元素后遍历i+1个元素;
    */
    void backtrack(vector<int>& candidates, int target, int i, int& sum, vector<vector<int>>& ans, vector<int>& sub_ans){
    
    
        if(sum>target) return;
        if(sum==target){
    
    
            ans.push_back(sub_ans);
            return;
        }
        for(int j=i; j<candidates.size(); j++){
    
    
            sub_ans.push_back(candidates[j]);
            sum += candidates[j];
            backtrack(candidates, target, j, sum, ans, sub_ans);
            sub_ans.pop_back();
            sum -= candidates[j];
        }
    }

    /*
    统计所有可能的排列情况:回溯算法
    1. 新建一维数组存储每个组合,新建二维数组存储最终结果;
    2. 找出 candidates 中所有可以使数字和为 target 的组合,所以定义sum变量用于存储当前组合的和;
    3. 递归遍历数组,不断计算符合条件的组合并push到答案中;
    */
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
    
    
        vector<vector<int>> ans;
        vector<int> sub_ans;
        int sum = 0;
        backtrack(candidates, target, 0, sum, ans, sub_ans);
        return ans;
    }
};

46. ​​Arreglo Completo

Dada una secuencia sin números repetidos, devuelve todas las permutaciones completas posibles.

Ejemplo:
Entrada: [1,2,3]
Salida:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1 ,2],
[3,2,1]
]

class Solution {
    
    
public:
    /*
    回溯思想:
    1. 当sub_ans中元素个数为nums中的元素个数时,保存;
    2. 循环遍历当前层,将遍历到的元素push进子集中;
    3. 将遍历到的元素添加到set中;
    4. 递归遍历更深层;
    5. 将该数在set中删除;
    6. 将该数去掉后继续遍历当前层;
    */
    void backtrack(vector<int>& nums, vector<int>& sub_ans, vector<vector<int>>& ans, set<int>& Set){
    
    
        if(sub_ans.size() == nums.size()){
    
    
            ans.push_back(sub_ans);
            return;
        }
        for(int i=0; i<nums.size(); i++){
    
    
            if(Set.find(nums[i])==Set.end()){
    
    
                sub_ans.push_back(nums[i]);
                Set.insert(nums[i]);
                backtrack(nums, sub_ans, ans, Set);
                Set.erase(nums[i]);
                sub_ans.pop_back();
            }
        }
    }

    /*
    所有可能的全排列:使用回溯算法,类似树的遍历
    要返回所有全排列,因此应该建立一个二位数组存放答案,其中每个1维数组是各个全排列;
    其中,为了避免全排列中包含相同元素,定义set用来记录已经遍历的元素;
    1. 递归遍历数组,不断计算新全排列并push到答案中;
    */
    vector<vector<int>> permute(vector<int>& nums) {
    
    
        vector<int> sub_ans;
        vector<vector<int>> ans;
        set<int> Set;
        backtrack(nums, sub_ans, ans, Set);
        return ans;
    }
};

78. Subconjunto

Dado un conjunto de números de matriz de enteros sin elementos repetidos, devuelva todos los subconjuntos posibles (conjuntos de potencia) de esa matriz.

Explicación: el conjunto de soluciones no puede contener subconjuntos duplicados.

Ejemplo:
Entrada: nums = [1,2,3]
Salida:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1 ,2],
[]
]

class Solution {
    
    
public:
    /*
    回溯思想:
    1. 结束条件是遍历到了数组末尾;
    2. 每遍历到一个数,push进子集,并将子集push到答案中;
    3. 继续递归遍历;
    4. 将该数去掉后继续遍历;
    */
    void backtrack(vector<int>& nums, int i, vector<int>& sub_ans, vector<vector<int>>& ans){
    
    
        if(i>nums.size()-1) return;
        sub_ans.push_back(nums[i]);
        ans.push_back(sub_ans);
        backtrack(nums, i+1, sub_ans, ans);
        sub_ans.pop_back();
        backtrack(nums, i+1, sub_ans, ans);
    }

    /*
    穷尽所有可能:使用回溯算法,类似树的遍历
    要返回所有子集,因此应该建立一个二位数组存放答案,其中每个1维数组是各个子集;
    1. 先保存空子集;
    2. 递归遍历数组,不断计算新子集并push到答案中;
    */
    vector<vector<int>> subsets(vector<int>& nums) {
    
    
        vector<vector<int>> ans;
        vector<int> sub_ans;
        ans.push_back(sub_ans);
        backtrack(nums, 0, sub_ans, ans);
        return ans;
    }
};

方法2class Solution {
    
    
public:
    /*
    回溯思想:
    1. 保存子集;
    2. 结束条件是遍历到了数组末尾;
    3. 循环遍历当前层,将遍历到的元素push进子集中;
    4. 递归遍历更深层;
    5. 将该数去掉后继续遍历当前层;
    */
    void backtrack(vector<int>& nums, int i, vector<int>& sub_ans, vector<vector<int>>& ans){
    
    
        ans.push_back(sub_ans);
        if(i==nums.size()) return;
        for(int j=i; j<nums.size(); j++){
    
    
            sub_ans.push_back(nums[j]);
            backtrack(nums, j+1, sub_ans, ans);
            sub_ans.pop_back();
        }
    }

    /*
    穷尽所有可能:使用回溯算法,类似树的遍历
    要返回所有子集,因此应该建立一个二位数组存放答案,其中每个1维数组是各个子集;
    1. 递归遍历数组,不断计算新子集并push到答案中;
    */
    vector<vector<int>> subsets(vector<int>& nums) {
    
    
        vector<int> sub_ans;
        vector<vector<int>> ans;
        backtrack(nums, 0, sub_ans, ans);
        return ans;
    }
};

90. Subconjunto II

Dada una matriz de números enteros que puede contener elementos duplicados, devuelva todos los subconjuntos posibles (conjuntos de potencia) de esa matriz.

Explicación: el conjunto de soluciones no puede contener subconjuntos duplicados.

Ejemplo:
Entrada: [1,2,2]
Salida:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]

class Solution {
    
    
public:
    /*
    回溯思想:
    1. 结束条件是遍历到了数组末尾;
    2. 每遍历到一个数,push进子集,
    3. 判断Set中是否存在该子集,如果不存在将子集push到答案中,并将子集insert到Set中;
    4. 继续递归遍历;
    5. 将该数去掉后继续遍历;
    */
    void backtrack(vector<int>& nums, int i, vector<int>& sub_ans, vector<vector<int>>& ans, set<vector<int>>& Set){
    
    
        if(i>nums.size()-1) return;
        sub_ans.push_back(nums[i]);
        if(Set.find(sub_ans)==Set.end()){
    
    
            ans.push_back(sub_ans);
            Set.insert(sub_ans);
        }
        backtrack(nums, i+1, sub_ans, ans, Set);
        sub_ans.pop_back();
        backtrack(nums, i+1, sub_ans, ans, Set);
    }

    /*
    穷尽所有可能:使用回溯算法,类似树的遍历,其中,需要注意数组有重复元素,但是答案不能包含重复子集
    要返回所有子集,因此应该建立一个二位数组存放答案,其中每个1维数组是各个子集;
    对于不能包含重复子集的情况,使用Set存储子集,用于判断是否重复
    1. 先保存空子集;
    2. 递归遍历数组,不断计算新子集并push到答案中,其中使用Set存储子集,用于判断是否重复;
    */
    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
    
    
        sort(nums.begin(), nums.end());
        vector<int> sub_ans;
        vector<vector<int>> ans;
        ans.push_back(sub_ans);
        set<vector<int>> Set;
        backtrack(nums, 0, sub_ans, ans, Set);
        return ans;
    }
};

方法2class Solution {
    
    
public:
    /*
    回溯思想:
    1. 保存子集;
    2. 结束条件是遍历到了数组末尾;
    3. 循环遍历当前层,当元素不为重复元素时,将遍历到的元素push进子集中;
    4. 递归遍历更深层;
    5. 将该数去掉后继续遍历当前层;
    */
    void backtrack(vector<int>& nums, int i, vector<int>& sub_ans, vector<vector<int>>& ans){
    
    
        ans.push_back(sub_ans);
        if(i==nums.size()) return;
        for(int j=i; j<nums.size(); j++){
    
    
            if(j>i && nums[j]==nums[j-1]) continue;
            sub_ans.push_back(nums[j]);
            backtrack(nums, j+1, sub_ans, ans);
            sub_ans.pop_back();
        }
    }

    /*
    穷尽所有可能:使用回溯算法,类似树的遍历
    要返回所有子集,因此应该建立一个二位数组存放答案,其中每个1维数组是各个子集;
    1. 递归遍历数组,不断计算新子集并push到答案中;
    */
    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
    
    
        sort(nums.begin(), nums.end());
        vector<int> sub_ans;
        vector<vector<int>> ans;
        backtrack(nums, 0, sub_ans, ans);
        return ans;
    }
};

Supongo que te gusta

Origin blog.csdn.net/weixin_43273742/article/details/107733277
Recomendado
Clasificación