20210325: recursividad de Likou, una colección de tipos retrospectivos de preguntas

Una colección de preguntas recursivas y retrospectivas.

tema

    1. Subconjunto

Inserte la descripción de la imagen aquí
2. 90. Subconjunto II
Inserte la descripción de la imagen aquí
3. 40. Suma de combinación II
Inserte la descripción de la imagen aquí
4. 22. Generación de paréntesis
Inserte la descripción de la imagen aquí

Ideas y algoritmos

    1. Subconjunto: la anotación es muy detallada y el subconjunto se genera de forma recursiva. También hay un método de operación de bits que es más conciso, pero será más laborioso si no es competente.
    1. Subconjunto II: El resto de las ideas son las mismas que en la pregunta anterior, la diferencia general es que los subconjuntos con el mismo desorden se eliminan clasificando y luego el conjunto se puede usar para eliminar duplicados.
    1. Suma de combinación II: Sobre la base de la pregunta anterior, continúe agregando condiciones, mientras obtiene todos los subconjuntos de manera recursiva, use el objetivo requerido por la pregunta para la poda.
    1. Generación de corchetes: también es una idea similar de este tipo de código recursivo, centrándose en comprender este proceso. Descubrí que los comentarios de la versión de Java enviados hace mucho tiempo son más detallados, y el cpp también está adjunto

Código

    1. Subconjunto
class Solution {
    
    
public:
    vector<vector<int>> subsets(vector<int>& nums) {
    
    
        vector<vector<int>> result;
        vector<int> item;
        // 一开始需要加入一个空集先
        result.push_back(item);
        generate(0,nums,item,result);
        return result;
    }

public:
    // 从nums[n]开始,一个一个选择放入item或者不放入item的加入result来获得所有子集
    void generate(int n,vector<int> &nums,vector<int> &item,vector<vector<int>> &result){
    
    
        if (n >= nums.size()) {
    
    
            return;
        }
        // 将nums[0]加入item,再放入result
        item.push_back(nums[n]);
        result.push_back(item);
        generate(n + 1,nums,item,result);
        // 或者不加入item,直接放入result
        item.pop_back();
        generate(n + 1,nums,item,result); 
    }
};
    1. Subconjunto II
class Solution {
    
    
public:
    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
    
    
        vector<vector<int>> result;
        vector<int> item;
        set<vector<int>> res_set;
        // 排序就可以去除顺序不同的相同子集,方便后续使用set进行去重
        sort(nums.begin(),nums.end());
        result.push_back(item);
        generate(0,nums,result,item,res_set);
        return result;
    }

private:
    void generate (int i,vector<int> & nums,vector<vector<int>> &result,vector<int> &item,set<vector<int>> &res_set) {
    
    
        if (i >= nums.size()) {
    
    
            return;
        }
        item.push_back(nums[i]);
        if (res_set.find(item) == res_set.end()) {
    
    
            result.push_back(item);
            res_set.insert(item);
        }
        generate(i + 1,nums,result,item,res_set);
        item.pop_back();
        generate(i + 1,nums,result,item,res_set);
    }
};
    1. Suma de combinación II
class Solution {
    
    
public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
    
    
        vector<vector<int>> result;
        vector<int> item;
        set<vector<int>> res_set;
        sort(candidates.begin(),candidates.end());
        generate(0,candidates,result,item,res_set,0,target);
        return result;
    }

private:
    void generate(int i,vector<int> &nums,vector<vector<int>> &result,vector<int> &item,set<vector<int>> &res_set,int sum,int target){
    
    
        if (i >= nums.size() || sum > target) {
    
    
            return;
        }
        sum += nums[i];
        item.push_back(nums[i]);
        if (  (target == sum) && res_set.find(item) == res_set.end()) {
    
    
            result.push_back(item);
            res_set.insert(item);
        }
        generate(i+1,nums,result,item,res_set,sum,target);
        sum -= nums[i];
        item.pop_back();
        generate(i+1,nums,result,item,res_set,sum,target);
    }
};
    1. Generación de soporte

Versión de anotación detallada de Java:

class Solution {
    
    
    
    private void generate(String item,int left,int right,List res) {
    
    
        //左括号和右括号满足上述条件的前提下都为n个,添加这个答案
        if(left == 0 && right == 0) {
    
    
            res.add(item);
            return;
        }
        //左括号的个数小于n 才能继续放左括号
        if(left > 0) {
    
    
            generate(item+"(",left-1,right,res);
        }
        //左括号个数必须大于右括号的放置个数 才能继续放右括号
        if(left < right) {
    
    
            generate(item+")",left,right-1,res);
        }
    }
    public List<String> generateParenthesis(int n) {
    
    
        /**
        *左括号个数必须大于右括号的放置个数 才能继续放右括号
        *左括号的个数小于n 才能继续放左括号
        *左括号和右括号满足上述条件的前提下都为n个,添加这个答案
        */
        List<String> res = new ArrayList<>();
        generate("",n,n,res);
        return res;
    }
}

Implementación de cpp:

class Solution {
    
    
public:
    vector<string> generateParenthesis(int n) {
    
    
        vector<string> result;
        generate("",n,n,result);
        return result;
    }

private:
    void generate (string item, int left,int right,vector<string> &result) {
    
    
        if (left == 0 && right == 0) {
    
    
            result.push_back(item);
            return;
        }
        if (left > 0) {
    
    
            generate(item+'(',left - 1,right,result);
        }
        if (left < right) {
    
    
            generate(item + ')',left,right - 1,result);
        }
    }
};

Escribir al final

  1. El pensamiento recursivo es una herramienta y un arma muy buena si se puede entender, y tiene efectos milagrosos al abordar los diversos tipos de violencia enumerados.
  2. El énfasis está en comprender la intención de la recursividad, en lugar de simplemente hacer una.

Supongo que te gusta

Origin blog.csdn.net/qq_36828395/article/details/115221419
Recomendado
Clasificación