回溯法案列总结

原创 2016年08月28日 16:00:32

格雷码转换本来是由一定规律的,但这里使用回溯法实现,具体解释在代码中有。注意n输入的是有多少位。

classSolution {

public:

    vector<int> grayCode(int n) {

        bitset<32> bits;//32位,每一位默认为0。

        vector<int> result;

        help(bits,result,n);

        return result;

    }

    void help(bitset<32>& bits,vector<int>& res, int k){

        if(k==0){

            res.push_back(bits.to_ulong());//需要将bits转换成无符号整数

        }

        else{

            help(bits,res,k-1);// 考虑位反转第k-1的情况

            bits.flip(k-1);//反转第 k-1位,

            help(bits,res,k-1);//考虑反转第k-1位的情况  

        }

    }

};

题目:全排列问题。通过交换每两个元素来实现。(元素不重复)

classSolution {

public:

    vector<vector<int>>permute(vector<int>& nums) {

        vector<vector<int> > res;

        vector<int> one=nums;

        if(nums.empty()){

            return res;

        }

        help(nums,0,one,res);

        return res;

    }

    void help(vector<int>& nums, intk, vector<int>& one, vector<vector<int>>& res){

        if(k==nums.size()){

            res.push_back(one);

            return;

        }

        for(int i=k;i<nums.size();i++){

            swap(one[k],one[i]);//交换第k和元素和其他元素

            help(nums,k+1,one,res);//第k处交换完之后,交换k+1和它之后的元素

            swap(one[k],one[i]);//交换回来

        }

    }

};

77.combinations即给定n和k,k代表从1~n中取出k个数

classSolution {

public:

    vector<vector<int>> combine(intn, int k) {

        vector<vector<int>> res;

        if(k>n||k<=0||n<=0){

            return res;

        }

        vector<int> one;

        help(n,1,k,one,res);

        return res;

    }

    void help(int n, int start, int k,vector<int>& one, vector<vector<int>>& res){

       //终止条件,k变成0,说明个数已经达到要求了。 

        if(k==0){

            res.push_back(one);

            return;

        }

        for(int i=start;i<=n;i++){

            one.push_back(i);

           help(n,<strong><em><u>i+1</u></em></strong>,k-1,one,res);//由于i位置考虑过了,那么下一个考虑的位置

//应该是i+1,如果把i+1改成start+1,那么将会导致可以取出同一个元素多次。

            one.pop_back();

        }

    }

};

78.子集合问题(集合元素不重复)

注意包括空集合

classSolution {

public:

   vector<vector<int>> subsets(vector<int>& nums) {

       vector<vector<int>> res;

       if(nums.empty()){

           return res;

       }

       vector<int> one;

       res.push_back(one);

       help(nums,0,one,res);

       return res;

   }

   void help(vector<int>& nums, int start, vector<int>&one, vector<vector<int>>& res){

       for(int<em><strong>i=start</strong></em>;i<nums.size();i++){//将start的位置都考虑了,就考虑start+1.

           one.push_back(nums[i]);

           res.push_back(one);

          help(nums,<strong><em>i+1</em></strong>,one,res);//注意这里是i+1.

           one.pop_back();

       }

   }

};

90子集合问题(集合元素可能重复)

classSolution {

public:

    vector<vector<int>>subsetsWithDup(vector<int>& nums) {

        vector<vector<int>> res;

        if(nums.empty()){

            return res;

        }

        sort(nums.begin(),nums.end());//由于可能含有重复的,所以进行排序,进行后序处理

        vector<int> one;

        res.push_back(one);

        help(nums,one,res,0);

        return res;

    }

//help函数可以理解从start处开始进行考虑,函数内的for循环表示遍历从start开始的所有位的情况,

//因此考虑完i位置的元素之后,应该从i+1位置继续考虑,递归完成。而由于元素可能相同,因此,

//后面重复的元素值的情况已经被之前相同元素的值考虑过了,直接跳过。

比如【2,2,3】{

考虑第一个2:[2][2,2][2,3][2,2,3]

第二个2的时候【2】,【2,3】重复了

第三个元素:【3】

}

    void help(vector<int>&nums,vector<int>& one,vector<vector<int>>& res,intstart){

        if(start>=nums.size()){

            return;

        }

        for(int i=start;i<nums.size();i++){

           if(i>start&&nums[i]==nums[i-1]){

                continue;

            }

            one.push_back(nums[i]);

            res.push_back(one);

            help(nums,one,res,i+1);

            one.pop_back();

        }

    }

};

17,电话号码的组合问题,即2-“abc”,3-"def"等,输入一组号码,输出可能的组合。

class Solution{
public:
    vector<string> letterCombinations(string digits) {
        vector<string> res;
        if(digits.empty()){
            return res;
        }
        string one;
        help(digits,one,res,0);
        return res;
    }
    void help(string digits, string& one,vector<string>& res, int start){
        if(start==digits.size()){
            res.push_back(one);
            return;
        }
        string letters=keys[digits[start]-'0'];
        for(int i=0;i<letters.size();i++){
            one.push_back(letters[i]);
            help(digits,one,res,start+1);//注意这里是start+1,因为//start位置已经全部考虑过了。
            one.pop_back();
        }
    }
private:
    stringkeys[10]={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
};
47全排列问题(元素可能重复)

这样我们也得到了在全排列中去掉重复的规则——去重的全排列就是从第一个数字起每个数分别与它后面非重复出现的数字交换。用编程的话描述就是第i个数与第j个数交换时,要求[i,j)中没有与第j个数相等的数.

class Solution {
public:
    vector<vector<int>>permuteUnique(vector<int>& nums) {
        sort(nums.begin(), nums.end());
      vector<vector<int>>result;
      permutation(nums, 0,result);
      return result;
    }
    
private:
       void permutation(vector<int>& nums, int start, vector<vector<int>>&result) {
              if (start>= nums.size() -1) {
                     result.push_back(nums);
                     return;
              }
              for (int i = start; i <nums.size(); i++) {
                    boolduplicate = false;
                  for(int j = ind; j < i; j++) {
                      if(nums[j] == nums[i]) {
                          duplicate = true;
                          break;
                      }
                  }
                  if(!duplicate) {
                   swap( nums[start],nums[i]);
                    permutation(nums, ind+1, result);
                   swap(nums[i], nums[start]);
                   }
                }
       }
};

40.combination sum2(每个数字只能选一次)

class Solution {
public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        vector<vector<int>> res;
        if(candidates.empty()){
            return res;
        }
        sort(candidates.begin(),candidates.end());
        vector<int> one;
        int currentsum=0;
        help(candidates,target,currentsum,one,res,0);
        return res;
    }
    void help(vector<int>& candidates, int target, int& currentsum, vector<int>& one, vector<vector<int>>& res, int index){
        if(target==currentsum){
            res.push_back(one);
            return;
        }
        else if(currentsum>target){
            return;
        }

        for(int i=index;i<candidates.size();i++){
            if(candidates[i]>target||(i!=0&&candidates[i]==candidates[i-1]&&i>index)){         //为了更好的理解,可以选一个例子【1,1,1,2】。当考虑过第一个1的时候,第二个1是可以忽略的,因为第二个1有的结果,第一个1都有了,我们可以一步步推导就能理解了。
                continue;
            }
            one.push_back(candidates[i]);
            currentsum+=candidates[i];
            help(candidates,target,currentsum,one,res,i+1);
            one.pop_back();
            currentsum-=candidates[i];
        }
    }
};
212、word search 2
思路,通过构造字典上完成,直接搜索给定矩阵来完成。而不是通过判断每一个单词是否在矩阵中来进行判断。
class TrieNode{
public:
    bool is_end;
    vector<TrieNode*> children;
    TrieNode(){
        is_end=false;
        children=vector<TrieNode*>(26, NULL);
    }   
};
class Trie{
public:
    TrieNode* getRoot(){return root;}
    Trie(vector<string>& words){
        root=new TrieNode();
        for(int i=0; i<words.size(); ++i)
            addWord(words[i]);
    }
    void addWord(const string& word){
        TrieNode* cur=root;
        for(int i=0; i<word.size(); ++i){
            int index=word[i]-'a';
            if(cur->children[index]==NULL)   
               cur->children[index]=new TrieNode();
            cur=cur->children[index];    
        }
        cur->is_end=true;
    }
private:
    TrieNode* root;
};

class Solution {
public:
    vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
        Trie* trie = new Trie(words);
        TrieNode* root=trie->getRoot();
        set<string> result_set;
        for(int x=0; x<board.size(); ++x)
            for(int y=0; y<board[0].size(); ++y)
                findWords(board, x, y, root, "", result_set);
        
        vector<string> result;
        for(auto it:result_set)   result.push_back(it);
        return result;        
    }
private:
    void findWords(vector<vector<char>>& board, int x, int y, TrieNode* root, string word, set<string>& result){
        if(x<0||x>=board.size()||y<0||y>=board[0].size() || board[x][y]==' ') return;
        
        if(root->children[board[x][y]-'a'] != NULL){
            word=word+board[x][y];
            root=root->children[board[x][y]-'a']; 
            if(root->is_end) result.insert(word);
            char c=board[x][y];
            board[x][y]=' ';
            findWords(board, x+1, y, root, word, result);
            findWords(board, x-1, y, root, word, result);
            findWords(board, x, y+1, root, word, result);
            findWords(board, x, y-1, root, word, result);
            board[x][y]=c;        
        }
    }
};
<span style="font-family: 'microsoft yahei';">class Solution {</span>
public:
    vector<vector<string>> partition(string s) {
        vector<vector<string> > ret;
        if(s.empty()) return ret;
        vector<string> path;
        dfs(0, s, path, ret);
        return ret;
    }
 void dfs(int index, string& s, vector<string>& path, vector<vector<string> >& ret) {
        if(index == s.size()) {
            ret.push_back(path);
            return;
        }
        for(int i = index; i < s.size(); ++i) {
            if(isPalindrome(s, index, i)) {
                path.push_back(s.substr(index, i - index + 1));
                dfs(i+1, s, path, ret);
                path.pop_back();
            }
        }
    }
    
    bool isPalindrome(const string& s, int start, int end) {
        while(start <= end) {
            if(s[start++] != s[end--])
                return false;
        }
        return true;
    }
};
37填数独矩阵
class Solution {
public:
    void solveSudoku(vector<vector<char>>& board) {
        if(board.empty()) return;
        solve(board);
    }
    bool solve(vector<vector<char>>& board){
        for(int i=0;i<9;i++){
            for(int j=0;j<9;j++){
                if(board[i][j]=='.'){
                    for(char c='1';c<='9';c++){
                        if(isvalid(board,i,j,c)){
                            board[i][j]=c;
                            if(solve(board)){
                                return true;
                            }
                            else{
                                board[i][j]='.';
                            }
                        }
                    }
                    return false;
                }
            }
        }
        return true;
    }
    bool isvalid(vector<vector<char>>& board, int i, int j, char c){
        for(int row=0;row<9;row++){
            if(board[row][j]==c){
                return false;
            }
        }
        for(int col=0;col<9;col++){
            if(board[i][col]==c){
                return false;
            }
        }
        for(int row=(i/3)*3;row<(i/3)*3+3;row++){
            for(int col=(j/3)*3;col<(j/3)*3+3;col++){
                if(board[row][col]==c){
                    return false;
                }
            }
        }
        return true;
    }
};



</pre><br /><br /><pre>
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

matlab智能算法案列

  • 2015-11-26 11:03
  • 50.00MB
  • 下载

关于美国雷斯法案修正案

一、关于美国雷斯法案修正案:     1、什么是美国雷斯法案?     2008年5月22日,美国雷斯法案修正案正式生效。这部禁止非法来源植物及其制成品(林产品)贸易的新法律,是对一部具有百年...

hhs整合法案

  • 2012-11-08 15:15
  • 22.38MB
  • 下载

谈 DevOps 自动化时,也应该考虑到 SOX 等法案

【编者按】对很多创业公司而言,随着业务的增长,网站的流量也会经历不同的阶段。从十万流量到一百万流量,再从一百万流量跨越到一千万甚至上亿的流量,网站的架构需要经历哪些变化?我们一起听听 58 同城的技术...

美国508法案

  • 2015-08-31 11:28
  • 343KB
  • 下载

程序员的《权利法案》

程序员应有的权利你都要去争取!而且记住:你可以让公司做出改变,要不然你就换一家公司。
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)