算法整理-回溯

一.  八皇后问题

     第一种解法将棋盘的所有格子都初始化为‘.’,  定义递归函数为前l-1行的格子已经排好(给定排面的情况下), 从第l层开始继续排得到的八皇后搜索结果。具体做法是从第l行的每一个列逐列尝试,如果不冲突则加入,再进行l+1的问题求解,求解完后进行回溯。空间复杂度为O(N*N)

class Solution {
public:
    int totalNQueens(int n) {
        vector<vector<int>> round(n, vector<int>(n, 0));
        int total = 0;
        btsearch(round, 0, n, total); return total; } private: void btsearch(vector<vector<int>> &round, int t, int n, int &total) { if (t == n) { total++; return; } for (int i = 0; i < n; i++) { if (isok(round, t, i)) { round[t][i] = 1; btsearch(round, t+1, n, total); round[t][i] = 0; } } } bool isok(const vector<vector<int>>round, int t, int j) { int n = round.size(); for (int c=0; c<t; c++) { if (round[c][j] == 1) return false; } for (int r=0; r<j; r++) { if (round[t][r] == 1) return false; } // 45 o for (int c=t-1, r=j+1; c>=0 && r<n; c--, r++) { if (round[c][r] == 1) return false; } // 135 o for (int c=t-1, r=j-1; c>=0 && r>=0; c--, r-- ) { if (round[c][r] == 1) return false; } // nqueque = 4。 return true; } };

 

class Solution {
public:
    int totalNQueens(int n) {
        vector<vector<int>> round(n, vector<int>(n, 0));
        int total = 0;
        btsearch(round, 0, n, total); return total; } private: void btsearch(vector<vector<int>> &round, int t, int n, int &total) { if (t == n) { total++; return; } for (int i = 0; i < n; i++) { if (isok(round, t, i)) { round[t][i] = 1; btsearch(round, t+1, n, total); round[t][i] = 0; } } } bool isok(const vector<vector<int>>round, int t, int j) { int n = round.size(); for (int c=0; c<t; c++) { if (round[c][j] == 1) return false; } for (int r=0; r<j; r++) { if (round[t][r] == 1) return false; }

 

 第二种方法类似,不过可以将格子表示成一个一维数组,第i个元素的值j表示将皇后放在第i行第j列

 

二. Permutation

 对一个数组进行全排列,无重复元素,定义递归函数为前i-1个元素全排列已经排好, 将第i个元素以及后面的元素进行全排列。过程为从第i个元素到最后一个元素轮流放在第i个位置上, 然后对第i+1个元素以及后续元素进行全排列。

class Solution {
public:
    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int>> res;
        permutehelper(nums, 0, res);
        return res; } private: void permutehelper(vector<int>&nums, int l, vector<vector<int>> &res){ if (l == nums.size()) { res.push_back(nums);} for (int i = l; i < nums.size(); i++) { swap(nums[l], nums[i]); permutehelper(nums, l+1, res); swap(nums[i], nums[l]); } } };

   若有重复,则先进行sort, 并且轮流当头那部分相同的数字只能出现一次,

class Solution {
public:
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        vector<vector<int>> res;
        sort(nums.begin(), nums.end());
        helper(nums, 0, res);
        return res; } private: void helper(vector<int>& nums, int l, vector<vector<int>> &res) { if (l == nums.size()) res.push_back(nums); set<int> vis; for (int i=l; i< nums.size(); i++) { if (vis.count(nums[i])) continue; vis.insert(nums[i]); swap(nums[l], nums[i]); helper(nums, l+1, res); swap(nums[i], nums[l]); } } };

 

三. 整数拆分

输入一个整数n,输出这个整数的所有划分方法,例如对于4,我们可以得到:4、3+1、2+1+1、1+1+1+1这四种划分方案。

为了使得有相同数字不同顺序组成的方案记作一种方案,我们另m表示当前整数划分方案中最大的数字,curSum表示当前方案已经构成的和,如果curSum==n则输出当前方案,否则尝试从m到1加入到方案中,并递归调用,注意回溯时,需要删除之前添加的数字。

void IntSplitPrint(int n, int m, int curSum, vector<int> & cur)
{
    if( curSum == n )
    {
        for( int i = 0 ; i < cur.size() ; i++ )
        {
            cout<<cur[i]<<" ";
        }
        cout<<endl;
    }
    else
    {
        for( int i = m ; i > 0 ; i-- )
        {
            if( i + curSum <= n )
            {
                cur.push_back(i);
                IntSplitPrint(n, i, curSum + i, cur);
                cur.pop_back();
            }
        }
    }
}

 

 

四. CombineSum

 在一组数字中,寻找子数组,使子数组的元素和为target的所有组合,求罗列所有组合,或求解组合总数,或求解最少使用的组合中元素个数(找零钱问题leetcode322)

求一个数组中所有的和等于target的组合。要求:

1.每个数可以用多次

2.没有重复的组合

3.一个组合中的所有的数是升序排列的

class Solution {
public:
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        vector<vector<int>> res;
        vector<int> out;
        btsearch(candidates, 0, target, out, res); return res; } void btsearch(vector<int> candidates, int l, int target, vector<int> &out, vector<vector<int>>&res) { if (target < 0) { return; } if (target == 0) { res.push_back(out); return; } for (int i = l ; i< candidates.size(); i++) { out.push_back(candidates[i]); btsearch(candidates, i, target - candidates[i], out, res); out.pop_back(); } } };

 

五. CombineSumII

求一个数组中所有的和等于target的组合。要求:

1.每个数最多只能使用一次

2.没有重复的组合

3.一个组合中的所有的数是升序排列的

class Solution {
public:
    vector<vector<int> > combinationSum2(vector<int> &num, int target) {
        vector<vector<int> > res;
        vector<int> out;
        sort(num.begin(), num.end());
        combinationSum2DFS(num, target, 0, out, res); return res; } void combinationSum2DFS(vector<int> &num, int target, int start, vector<int> &out, vector<vector<int> > &res) { if (target < 0) return; else if (target == 0) res.push_back(out); else { for (int i = start; i < num.size(); ++i) { if (i > start && num[i] == num[i - 1]) continue; out.push_back(num[i]); combinationSum2DFS(num, target - num[i], i + 1, out, res); out.pop_back(); } } } };

 

六. subsets

https://www.cnblogs.com/TenosDoIt/p/3451902.html

给定一个整数的set, 给出所有的子set。无重复数字。每一个元素有选择放或者不放两种选择。

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>> res;
        vector<int> out;
        helper(nums, 0, out, res); return res; } private: void helper(vector<int>nums, int l, vector<int>&out, vector<vector<int>>&res) { if (l == nums.size()) { res.push_back(out); return; } out.push_back(nums[l]); helper(nums, l+1, out, res); out.pop_back(); helper(nums, l+1, out, res); } };

 

转载于:https://www.cnblogs.com/cookcoder-mr/p/11080053.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值