算法-回溯

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;
            }  
        }
    }
};

 

posted @ 2019-06-23 21:16  COOHAHAHA  阅读(133)  评论(0编辑  收藏  举报