【递归、搜索与回溯】综合练习

在这里插入图片描述

欢迎来到Cefler的博客
博客主页:那个传说中的man的主页
个人专栏:题目解析
推荐文章:题目大解析(3)


目录

  • 找出所有子集的异或总和再求和
  • 全排列 II
  • 电话号码的字母组合
  • 括号生成
  • 组合
  • 目标和

找出所有子集的异或总和再求和

原题链接:找出所有子集的异或总和再求和

mycode:

class Solution {
public:
    vector<vector<int>> res;
    vector<int> path;
    void dfs(vector<int>& nums,int n)
    {
        for(int i = n ;i<nums.size();i++)
        {
            path.push_back(nums[i]);
            dfs(nums,i+1);

            path.pop_back();
        }

        res.push_back(path);
    }
    int subsetXORSum(vector<int>& nums) {
        dfs(nums,0);
        int Sum  = 0;
        for(int i = 0;i<res.size();i++)
        {
            int sum = 0;
            for(auto e:res[i])
            {
                sum^=e;
            }
            Sum+=sum;
        }
        return Sum;
    }
};

优化代码(纯递归):

class Solution {
public:
    int Sum = 0,sum = 0;
    void dfs(vector<int>& nums,int n)
    {
        for(int i = n ;i<nums.size();i++)
        {
            sum^=nums[i];
            dfs(nums,i+1);
            sum^=nums[i];//再异或一遍可以消掉
        }
       Sum+=sum;
    }
    int subsetXORSum(vector<int>& nums) {
        dfs(nums,0);
        return Sum;
    }
};

全排列 II

原题链接:全排列 II

mycode:

class Solution {
public:
    vector<vector<int>> ret;
    vector<int> path;
   
    bool check[8];//检查该位置是否被用过了,true说明被用过了 
    void dfs(vector<int>& nums)
    {
        if(nums.size()==path.size())//说明此时已经组成一个序列了
        {
            ret.push_back(path);
            return;
        }
        for(int i = 0;i<nums.size();i++)
        {
            if(check[i]==false && (i==0||nums[i]!=nums[i-1]||check[i-1]==true))//此时还没被用过&&第一层||前后值不重复相等||不在同一层
            {
                path.push_back(nums[i]);
                check[i] = true;
                dfs(nums);
                //回溯清空现场,将dfs下层插入的元素pop掉
                path.pop_back();
                check[i] = false;
                

            }
        }
    }

    vector<vector<int>> permuteUnique(vector<int>& nums) {
        //前提先排序
        sort(nums.begin(),nums.end());
        dfs(nums);
        return ret;
    }
};

【递归、搜索与回溯】综合练习_第1张图片

电话号码的字母组合

原题链接:电话号码的字母组合

mycode:

class Solution {
public:
   const char* numsArr[10] = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
   void Combine(const string& digits,string combinestr,int i ,vector<string>& ret)
   {
       if(i == digits.size())//当数字中的字母全部都进行完组合后
       {
           ret.push_back(combinestr);
           return;
       }
      int num = digits[i] - '0';
      string str = numsArr[num];
       for(auto ch:str)
       {
           Combine(digits,combinestr+ch,i+1,ret);
       }
   }
    vector<string> letterCombinations(const string& digits) {
           vector<string> v;//存储全部组合的字符串
           if(digits=="")
           return v;
           string str;//这个是专门用来组合的字符串
           int i =0;
           Combine(digits,str,i,v);
           return v;
 
    }
};

加入恢复现场代码优化

class Solution {
public:
   const char* numsArr[10] = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
   vector<string> ret;
   string combinestr;
   void Combine(const string& digits,int i )
   {
       if(i == digits.size())//当数字中的字母全部都进行完组合后
       {
           ret.push_back(combinestr);
           return;
       }
      int num = digits[i] - '0';
      string str = numsArr[num];
       for(auto ch:str)
       {
           combinestr+=ch;
           Combine(digits,i+1);
           //恢复现场
           combinestr.pop_back();
       }
   }
    vector<string> letterCombinations(const string& digits) {
           if(digits=="")
           return ret;
           Combine(digits,0);
           return ret;
 
    }
};

括号生成

原题链接:括号生成

mycode:

class Solution {
public:
    vector<string> ret;
    string path;
    int left = 0,right = 0;
    void dfs(int n)
    {
        if(left+right==2*n) 
        {
            ret.push_back(path);
            return;
        }
        if(left<n)
      {
            path.push_back('(');
            left++;
            dfs(n);
            path.pop_back();
            left--;
      }
      if(right<left)
      {
          path.push_back(')');
          right++;
          dfs(n);
            path.pop_back();
            right--;
      }    
    }
    vector<string> generateParenthesis(int n) {
        dfs(n);
        return ret;
    }
};

【递归、搜索与回溯】综合练习_第2张图片

组合

原题链接:组合

mycode:

class Solution {
public:
    vector<vector<int>> ret;
    vector<int> path;
    int _k;
    void dfs(int n,int pos)
    {
         if(path.size()==_k)
            {
                ret.push_back(path);
                return;
            }
        for(int i = pos;i<=n;i++)
        {
            path.push_back(i);
            dfs(n,i+1);//i+1是换层,n+1是在同一层里换元素
            //恢复现场
            path.pop_back();
        }
    }
    vector<vector<int>> combine(int n, int k) {
        _k = k;
        dfs(n,1);
        return ret;
    }
};

【递归、搜索与回溯】综合练习_第3张图片

如这种左大右小的树,一般就是i+1进行深度优先遍历,如果是完全二叉树,则是n+1这种广度遍历

目标和

原题链接:目标和

mycode1:

class Solution {
public:
    int count = 0;
    int _target;
    void dfs(vector<int>& nums,int i,int sum)
    {
        if(i==nums.size()) 
        {
            if(sum == _target) count++;
            return;
        }
        dfs(nums,i+1,sum+nums[i]);//加
        dfs(nums,i+1,sum-nums[i]);//减
    }
    int findTargetSumWays(vector<int>& nums, int target) {
        _target = target;
        dfs(nums,0,0);
        return count;
    }
};

mycode2:

class Solution {
public:
    int count = 0;
    int _target;
    int sum = 0;
    void dfs(vector<int>& nums,int i)
    {
        if(i==nums.size()) 
        {
            if(sum == _target) count++;
            return;
        }
        sum+=nums[i];
        dfs(nums,i+1);
        //恢复现场
        sum-=nums[i];

        sum-=nums[i];
        dfs(nums,i+1);
        //恢复现场
        sum+=nums[i];

    }
    int findTargetSumWays(vector<int>& nums, int target) {
        _target = target;
        dfs(nums,0);
        return count;
    }
};

你可能感兴趣的:(递归,搜索与回溯,算法,递归,回溯,深搜)