zoukankan      html  css  js  c++  java
  • 算法-回溯

    1.给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

    说明:解集不能包含重复的子集。

    示例:

    输入: nums = [1,2,3]
    输出:
    [
      [3],
      [1],
      [2],
      [1,2,3],
      [1,3],
      [2,3],
      [1,2],
      []
    ]

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/subsets
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

     1 class Solution {
     2      void generate(vector<int> sub,vector<int>& nums,int i,vector<vector<int>>& result){
     3         if(i==nums.size()) return;
     4         sub.push_back(nums[i]);
     5         result.push_back(sub);
     6         generate(sub,nums,i+1,result);
     7         vector<int> next=sub;
     8         next.pop_back();//回溯
     9         generate(next,nums,i+1,result);
    10     }
    11 public:
    12     vector<vector<int>> subsets(vector<int>& nums) {
    13         vector<vector<int>> result;
    14         vector<int> sub;
    15         result.push_back(sub);
    16         generate(sub,nums,0,result);
    17         return result;
    18         
    19     }
    20 };

    位运算方法

    class Solution{
    public:
        vector<vector<int>> subsets(vector<int>& nums) {
            vector<vector<int>> result;
            int n=nums.size();
            int len=1<<n;//结果总长度
            for(int i=0;i<len;++i){
                vector<int> sub;
                for(int j=0;j<n;++j){
                    if(i & (1<<j)){//与1,2,4分别进行“与”运算,得到是否将数字放入数组
                        sub.push_back(nums[j]);
                    }
                }
                result.push_back(sub);
            }
            return result;        
        }
    };

    2.给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

    说明:解集不能包含重复的子集。

    示例:

    输入: [1,2,2]
    输出:
    [
      [2],
      [1],
      [1,2,2],
      [2,2],
      [1,2],
      []
    ]

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/subsets-ii
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    class Solution {
        void generate(vector<int> sub,int i,vector<int>& nums,vector<vector<int>>& result,set<vector<int>>& res_set){
            if(i>=nums.size()) return;
            sub.push_back(nums[i]);
            if(res_set.find(sub)==res_set.end()){
                res_set.insert(sub);
                result.push_back(sub);
            }
            generate(sub,i+1,nums,result,res_set);  
            sub.pop_back();
            generate(sub,i+1,nums,result,res_set);
            
        }
    public:
        vector<vector<int>> subsetsWithDup(vector<int>& nums) {
            vector<vector<int>> result;
            set<vector<int>> res_set;//去重
            sort(nums.begin(),nums.end());//排序
            vector<int> sub;
            result.push_back(sub);
            res_set.insert(sub);
            generate(sub,0,nums,result,res_set);
            return result;
        }
    };

    3.给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

    candidates 中的每个数字在每个组合中只能使用一次。

    说明:

        所有数字(包括目标数)都是正整数。
        解集不能包含重复的组合。

    示例 1:

    输入: candidates = [10,1,2,7,6,1,5], target = 8,
    所求解集为:
    [
      [1, 7],
      [1, 2, 5],
      [2, 6],
      [1, 1, 6]
    ]

    示例 2:

    输入: candidates = [2,5,2,1,2], target = 5,
    所求解集为:
    [
      [1,2,2],
      [5]
    ]

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/combination-sum-ii
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    class Solution {
    public:
        int n;
        vector<vector<int>> result;
        vector<int> sub;
        vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
            n=candidates.size();
            sort(candidates.begin(),candidates.end());
            generate(candidates,target,0);
            return result;
        }
        
        void generate(vector<int>& candidates,int target,int index){
            if(target<0){
                return;
            }else if(target==0){
                result.push_back(sub);
                return;
            }else{
                for(int i=index;i<n && candidates[i]<=target;++i){
                    if(i>index && candidates[i-1]==candidates[i]) continue; //去重           
                    sub.push_back(candidates[i]);
                    generate(candidates,target-candidates[i],i+1);
                    sub.pop_back();
                } 
            }
        }
    };

    4.给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。

    例如,给出 n = 3,生成结果为:

    [
      "((()))",
      "(()())",
      "(())()",
      "()(())",
      "()()()"
    ]

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/generate-parentheses
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    class Solution {
        vector<string> result; 
        int max;
    public:
        vector<string> generateParenthesis(int n) {
            int l=0,r=0;
            max=n;
            generate(l,r,"");
            return result;
        }
        void generate(int l,int r,string s){
            if(r==max){
                result.push_back(s);
                return;
            }
            if(l>=r){
                if(l<max) generate(l+1,r,s+'(');
                if(l!=r){
                    if(r<max) generate(l,r+1,s+')'); 
                }                  
            }
        }
    };

     5.n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
    给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
    每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
    示例:
    输入: 4
    输出: [
     [".Q..",  // 解法 1
      "...Q",
      "Q...",
      "..Q."],

     ["..Q.",  // 解法 2
      "Q...",
      "...Q",
      ".Q.."]
    ]
    解释: 4 皇后问题存在两个不同的解法。

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/n-queens
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    class Solution {
        vector<string> solve;
        vector<vector<string>> result;
        int n;
    public:
        vector<vector<string>> solveNQueens(int n) {
            vector<vector<int>> canPutQueen;
            this->n=n;
            for(int i=0;i<n;++i){
                vector<int> v;
                canPutQueen.push_back(v);
                string s;
                solve.push_back(s);
                for(int j=0;j<n;++j){
                    solve[i].push_back('.');
                    canPutQueen[i].push_back(0);
                }
            }
            putQueen(0,0,canPutQueen);
            return result;    
            
        }
        void putQueen(int i,int j,vector<vector<int>>& canPutQueen){                 
            if(i==n) {
                result.push_back(solve); 
                return;
            }
            if (j == n) return;//此处要先判定j==n,否则下面vector会访问越界
            if(canPutQueen[i][j]>0){
                if(j==n-1) return;
                putQueen(i,j+1,canPutQueen);
            }else{
                solve[i][j]='Q';
                setCanPutQueen(i,j,canPutQueen,1);
                putQueen(i+1,0,canPutQueen); 
                solve[i][j]='.';
                setCanPutQueen(i,j,canPutQueen,-1);
                putQueen(i,j+1,canPutQueen);
            }     
        }
        //设置可放标志数组,可回撤
        void setCanPutQueen(int i,int j,vector<vector<int>>& canPutQueen,int m){
            for(int k=0;k<n;k++){
                canPutQueen[i][k]+=m;
                canPutQueen[k][j]+=m; 
                if(i+j-k>=0&&i+j-k<n){
                    canPutQueen[k][i+j-k]+=m; 
                }
                if(k+j-i>=0&&k+j-i<n){
                    canPutQueen[k][k+j-i]+=m;
                }  
            }
        }
    };
  • 相关阅读:
    R语言学习笔记2——绘图
    稀疏编码笔记1
    【转】宏定义中##和#的作用
    CRUX下实现进程隐藏(3)
    CRUX下实现进程隐藏(2)
    CRUX下实现进程隐藏(1)
    Coursera机器学习基石 第1讲:The Learning Problem
    R语言学习笔记1——R语言中的基本对象
    Semi-Supervised Dimensionality Reduction
    转发常见一主从复制案例
  • 原文地址:https://www.cnblogs.com/chendaniu/p/11060956.html
Copyright © 2011-2022 走看看