分治、回溯

分治、回溯

递归状态树

分治Divide&Conquer

分治代码模板

def divide_conquer(problem,param1,param2,……):
# resursion terminator
if problem is None:
    print_result
    return 
# prepare data
data = prepare_data(problem)
subproblems=split_problem(problem,data)

# conquer subproblems
subresult1 = self.divide_conquer(subpromblems[0],p1,……)
subresult2 = self.divide_conquer(subpromblems[1],p1,……)
subresult3 = self.divide_conquer(subpromblems[2],p1,……)
……
# process and generate the final result
result = process_result(subresult1,subresult2,subresult3,……)

回溯Backtracking

回溯法采用试错的思想,它尝试分布的去解决一个问题。在分步解决问题的过程中,当它通过尝试发现现有的分步答案不能得到有效的正确的解答的时候,它将取消上一步甚至是上几步的计算,再通过其他的可能的分步解答再次尝试寻找问题的答案。

回溯法通常用最简单的递归方法来实现,在反复重试上述的步骤后可能出现两种情况:

  • 找到一个可能存在的正确的答案;
  • 在尝试了所有可能的分步方法后宣告该问题没有答案。
    在最坏的情况下,回溯法会导致一次复杂度为指数时间的计算。

Pow(x, n)

class Solution {
public:
    double myPow(double x, int n) {
        if(n==0)
        return 1;
        long long N=n;
        if(n<0)
        {
            N=-N;
            x=1/x;
        }
        return (N%2==0)?myPow(x*x,N/2):x*myPow(x*x,N/2);
    }
};

子集

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        int S = nums.size();
        int N = 1 << S;
        vector<vector<int> > res;
        for (int i = 0; i < N; ++i) {
            vector<int> v;
            for (int j = 0; j < S; ++j)
                if (i & (1 << j))
                    v.push_back(nums[j]);
            res.push_back(v);
        }
        return res;
    }
};

多数元素

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int target = nums[0];
        int count = 1;
        for(int i = 1;i<nums.size();i++)
            if(nums[i]!=target)  
            {  
                count--;
                if(count==0)
                {
                    target = nums[i];
                    count = 1;
                }
            }else count++;
      return target;
    }
};

电话号码的字母组合

class Solution {
public:
    vector<string> letterCombinations(string digits) {

        vector<string> m = {
            "",
            "", "abc","def",
            "ghi","jkl","mno",
            "pqrs","tuv","wxyz"
        };

        vector<string> res;
        if (digits.size() == 0) return res;
        string s;

        DFS(digits, 0, s, res,m);
        return res;
    }

    void DFS(string digits, int pos, string & s, vector<string> &res, vector<string>& m){
        if (pos == digits.size()){
            res.push_back(s);
            return ;
        }
        //获取对应键盘的字母
        string tmp = m[digits[pos] - '0'];
        for (int i = 0; i < tmp.size(); i++){
            s.push_back(tmp[i]);
            DFS(digits, pos+1, s, res, m);
            s.pop_back();
        }
        return ;
    }
};

N皇后

class Solution {
public:
    void solve(vector<vector<string>>& res, vector<string>& tmp, vector<bool>& cols_, vector<bool>& diag1s_, vector<bool>& diag2s_, int n, int row){
        if(row == n){
            res.push_back(tmp);
            return;
        }
        for(auto col = 0; col < n; col++){
            int ll = row + col;
            int rr = row - col + n - 1;
            if (cols_[col] && diag1s_[ll] && diag2s_[rr]){
                tmp[row][col] = 'Q';
                cols_[col] = false;
                diag1s_[ll] = false;
                diag2s_[rr] = false;

                solve(res, tmp, cols_, diag1s_, diag2s_, n, row+1);

                tmp[row][col] = '.';
                cols_[col] = true;
                diag1s_[ll] = true;
                diag2s_[rr] = true;
            }
        }
    }
    
    vector<vector<string>> solveNQueens(int n) {
        vector<vector<string>> res;
        vector<string> tmp(n, string(n, '.'));
        vector<bool> cols_(n, true);
        vector<bool> diag1s_(2*n-1, true);
        vector<bool> diag2s_(2*n-1, true);
        solve(res, tmp, cols_, diag1s_, diag2s_, n, 0);
        return res;
    }
};

猜你喜欢

转载自www.cnblogs.com/liugangjiayou/p/12398647.html
今日推荐