您的位置:首页 > 其它

回溯法案列总结

2016-08-28 16:00 260 查看
格雷码转换本来是由一定规律的,但这里使用回溯法实现,具体解释在代码中有。注意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>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  回溯法