剑指offer 第二版(81——100)

这篇文章介绍了使用递归和动态规划方法解决组合、全排列以及相关问题的算法,包括含有特定数量元素的组合、允许重复和不允许重复的选择元素组合、含有重复元素集合的全排列、无重复元素集合的全排列等。每个问题都给出了相应的代码实现,通过遍历、剪枝和状态转移矩阵来找到最优解。
摘要由CSDN通过智能技术生成

剑指 Offer II 080. 含有 k 个元素的组合

 vector<vector<int>> res;
    vector<vector<int>> combine(int n, int k) {
        vector<int> xx;
        dfs(n,k,1,xx);
        return res;
    }
    void dfs(int n,int  k,int idx,vector<int> xx){
        if(xx.size()==k){
            res.push_back(xx);
            return ;
        }
        for(int i=idx;i<=n;i++){
            xx.push_back(i);
            dfs(n,k,i+1,xx);
            xx.pop_back();
        }
    }

 剑指 Offer II 081. 允许重复选择元素的组合

vector<vector<int>>  res;
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        vector<int> xx;
        dfs(0,0,target,candidates,xx);
        return res;
    }
    void dfs(int sum,int idx,int target,vector<int> nums,vector<int> recode){
        if(sum>target) return ;
        if(sum==target){
            res.push_back(recode);
            return ;
        }
        for(int i=idx;i<nums.size();i++){
            sum+=nums[i];
            recode.push_back(nums[i]);
            dfs(sum,i,target,nums,recode);
            recode.pop_back();
            sum-=nums[i];
        }
    }

 剑指 Offer II 082. 含有重复元素集合的组合

    vector<bool> st;
    vector<vector<int>> res;
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        for(int i=0;i<candidates.size();i++) st.push_back(false);
        sort(candidates.begin(),candidates.end());
        vector<int> xx;
        dfs(0,0,target,candidates,xx);
        return res;
    }
    void dfs(int sum,int idx,int target,vector<int> nums,vector<int> recode){
        if(sum>target) return ;
        if(sum==target){
            res.push_back(recode);
            return ;
        }
        for(int i=idx;i<nums.size();i++){
            if(i&&nums[i]==nums[i-1]&&!st[i-1]) continue;
            st[i]=true;
            sum+=nums[i];
            recode.push_back(nums[i]);
            dfs(sum,i+1,target,nums,recode);
            recode.pop_back();
            sum-=nums[i];
            st[i]=false;
        }
    }

 剑指 Offer II 083. 没有重复元素集合的全排列

vector<vector<int>> res;
    vector<bool> st;
    int n=0;
    vector<vector<int>> permute(vector<int>& nums) {
        n=nums.size();
        for(int i=0;i<n;i++) st.push_back(false);
    
        vector<int> xx;
        dfs(0,xx,nums);
        return res;
    }
    void dfs(int idx,vector<int> xx,vector<int> nums){
        if(xx.size()==n){
            res.push_back(xx);
            return  ;
        } 
        
        for(int i=0;i<nums.size();i++){
            if(st[i]) continue;
            st[i]=true;
            xx.push_back(nums[i]);
            dfs(i,xx,nums);
            xx.pop_back();
            st[i]=false;
        }
       
    }

 剑指 Offer II 084. 含有重复元素集合的全排列 

vector<vector<int>> res;
    vector<bool> st;
    int n=0;
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        vector<int>xx;
        n=nums.size();
        for(int i=0;i<n;i++) st.push_back(false);
        dfs(0,xx,nums);
        return res;
    }
    void dfs(int idx,vector<int> xx,vector<int> nums){
        if(xx.size()==n){
            res.push_back(xx);
            return  ;
        } 
        
        for(int i=0;i<nums.size();i++){
            if(st[i]) continue;
            if(i&&!st[i-1]&&nums[i]==nums[i-1]) continue;
            st[i]=true;
            xx.push_back(nums[i]);
            dfs(i,xx,nums);
            xx.pop_back();
            st[i]=false;
        }
    }
       

 剑指 Offer II 085. 生成匹配的括号

 string m="()";
    vector<string> res;
    vector<string> ans;
    vector<string> generateParenthesis(int n) {
        string xx;
        dfs(n,xx);
        for(int i=0;i<res.size();i++){
            int cnt=0;
            int tt=0;
            bool flag=true;
            for(int j=0;j<res[i].size();j++){
                if(res[i][j]==')'){
                    if(tt) tt--;
                    else {
                        flag=false;
                        break;
                    }
                }
                else tt++; 
            }
            if(flag&&tt==0) ans.push_back(res[i]);
        }
        return ans;
    }
    void dfs(int n,string xx){
        if(xx.size()==n*2){
            res.push_back(xx);
            return ;
        } 
        for(int i=0;i<2;i++){
            xx.push_back(m[i]);
            dfs(n,xx);
            xx.pop_back();
        }
    }

 剑指 Offer II 086. 分割回文子字符串

 vector<vector<string>> res;
    int n;
    bool f[16][16];
    vector<vector<string>> partition(string s) {
        n=s.size();
        memset(f,0,sizeof(f));
        vector<string> xx;
                
        for(int i=n;i>=0;i--){
            for(int j=i;j<n;j++){
                if(i==j)  f[i][j]=1;
                if(j==i+1&&s[i]==s[j])   f[i][j]=1;
                if(j-i>1&&f[i+1][j-1]&&s[i]==s[j]) f[i][j]=1;
            }
        }
        dfs(0,s,xx);
        return res;
    }
    void dfs(int idx, string s,vector<string> xx){
        if(idx==s.size()){
            res.push_back(xx);
            return ;
        } 
        for(int i=idx;i<n;i++){
           if(f[idx][i]){
               xx.push_back(s.substr(idx,i-idx+1));
               dfs(i+1,s,xx);
               xx.pop_back();
           } 
        }
    }

 剑指 Offer II 087. 复原 IP 

 vector<string> res;
    vector<string> restoreIpAddresses(string s) {
        string xx;
        dfs(0,s,xx);
        return res;
    }
    void dfs(int idx,string s,string xx){
       
        if(idx==s.size()&&count(xx.begin(),xx.end(),'.')==4){
            xx.pop_back();
            res.push_back(xx);
            return ;
        }  
        if(idx>=s.size()||count(xx.begin(),xx.end(),'.')>=4)    return;
        for(int len=1;len<=3;len++){
            string str=s.substr(idx,len);
            
            if(atoi(str.c_str())>255) continue;
            if(str.size()>1&&str[0]=='0') continue;
            
            string ori=xx;
            xx+=str+'.';
            dfs(idx+len,s,xx);
            xx=ori;
        }
    }

 剑指 Offer II 088. 爬楼梯的最少成本

int minCostClimbingStairs(vector<int>& cost) {
        int f[cost.size()+1];
        memset(f,0,sizeof(f));
        f[0]=0;
        f[1]=0;
        for(int i=2;i<=cost.size();i++){
            f[i]=min(f[i-1]+cost[i-1],f[i-2]+cost[i-2]);
        }
        return f[cost.size()];

    }

 剑指 Offer II 089. 房屋偷盗

int rob(vector<int>& nums) {
        if(nums.size()==1) return nums[0];
        int f[nums.size()];
        memset(f,0,sizeof(f));
        f[0]=nums[0];f[1]=nums[1];
        for(int i=0;i<nums.size();i++){
            for(int j=i-2;j>=0;j--){
                f[i]=max(f[i],f[j]+nums[i]);
            }
        }
        return max(f[nums.size()-1],f[nums.size()-2]);

    }

 剑指 Offer II 090. 环形房屋偷盗

 int rob(vector<int> nums,int start,int end){
        if(start==end) return nums[start];
        int f[nums.size()];
        memset(f,0,sizeof(f));
        f[start]=nums[start];f[start+1]=nums[start+1];
        for(int i=start+2;i<=end;i++){
            for(int j=start;j<=i-2;j++){
              //  cout<<i<<" "<<j<<" "<<start<<" "<<end<<endl;
                f[i]=max(f[i],f[j]+nums[i]);
            }
        }
       // int xx=f[end];
        //cout<<xx<<endl;
      //  if(end-1>=start) xx=max(xx,f[end-1]); cout<<xx<<endl;
        return max(f[end],f[end-1]);
    }
    int rob(vector<int>& nums) {
        if(nums.size()==0) return 0;
        if(nums.size()==1) return nums[0];
        return max(rob(nums,0,nums.size()-2),rob(nums,1,nums.size()-1));
    }

 剑指 Offer II 091. 粉刷房子

int minCost(vector<vector<int>>& costs) {
        int n=costs.size();
        int f[n][3];
        memset(f,0,sizeof(f));
        f[0][0]=costs[0][0];
        f[0][1]=costs[0][1];
        f[0][2]=costs[0][2];
       
        for(int i=1;i<n;i++){
            f[i][0]=min(f[i-1][1],f[i-1][2])+costs[i][0];
            f[i][1]=min(f[i-1][0],f[i-1][2])+costs[i][1];
            f[i][2]=min(f[i-1][0],f[i-1][1])+costs[i][2];
        } 
        return min(min(f[n-1][0],f[n-1][1]),f[n-1][2]);
    }

 剑指 Offer II 092. 翻转字符

int minFlipsMonoIncr(string s) {
        int f[s.size()];
        memset(f,0,sizeof(f));
        if(s[0]=='1') f[0]=1;
       for(int i=1;i<s.size();i++){
           if(s[i]=='1') f[i]=f[i-1]+1;
           else f[i]=f[i-1];
       } 
        int n=s.size();
        int res=INT_MAX;
       for(int i=0;i<n;i++){
            int one=0,zero=0;
            if(i==0){
                one=0;
                zero=n-1-(f[n-1]-f[0]);
            }else if(i==n-1){
                zero==0;
                one=f[n-2];
                
            }else{
                one=f[i-1];
                zero=n-(i+1)-(f[n-1]-f[i]);
            }
            res=min(res,one+zero);
            
       }
       return res;
    }

 剑指 Offer II 093. 最长斐波那契数列

int lenLongestFibSubseq(vector<int>& arr) {
        int n=arr.size();
        unordered_map<int ,int >map;
        for(int i=0;i<n;i++) map[arr[i]]=i;

        vector<vector<int>> f(n,vector<int>(n));
        int res=0;
        
        for(int i=0;i<n;i++){
            for(int j=0;j<i;j++){
                int x=arr[i]-arr[j];
                f[j][i]=2;
                if(map.count(x)&&x<arr[j]){
                    int k=map[x];
                    f[j][i]=max(f[j][i],f[k][j]+1);
                    res=max(res,f[j][i]);
                }
            }
        }
        if(res<3) return 0;
        return res;
    }

剑指 Offer II 094. 最少回文分割

 int minCut(string s) {
        s=' '+s;
        int n=s.size();
        int f[n];
        memset(f,0,sizeof(f));
        vector<vector<bool>> st(n,vector<bool>(n));
        for(int j=n-1;j>=1;j--){
            for(int i=j;i<n;i++){
                if(i==j) st[j][i]=true;
                if(i-j==1&&s[i]==s[j]) st[j][i]=true;
                if(i-j>1&&s[i]==s[j]&&st[j+1][i-1]) st[j][i]=true;
            }
        }
        f[0]=0;
        for(int i=1;i<n;i++){
            f[i]=INT_MAX;
            if(st[1][i]) {
                f[i]=0;
                continue;
            }
            for(int j=1;j<=i;j++){
                if(st[j][i]) f[i]=min(f[i],f[j-1]+1);
            }
        }
        return f[n-1];
    }

 剑指 Offer II 095. 最长公共子序列

int longestCommonSubsequence(string text1, string text2) {
       int f[text1.size()+1][text2.size()+1];
       memset(f,0,sizeof(f));
       for(int i=1;i<=text1.size();i++){
           for(int j=1;j<=text2.size();j++){
              if(text1[i-1]==text2[j-1]) f[i][j]=max(f[i][j],f[i-1][j-1]+1);
              else f[i][j]=max(f[i-1][j],f[i][j-1]);
           }
       }
       return f[text1.size()][text2.size()];
    }

 剑指 Offer II 096. 字符串交织

bool isInterleave(string s1, string s2, string s3) {
        if(s1.size()+s2.size()!=s3.size()) return false;
        int n=s1.size(),m=s2.size();
        s1=" "+s1,s2=" "+s2,s3=" "+s3;
        vector<vector<bool>> f(n+1,vector<bool> (m+1));
        f[0][0]=true;  
        for(int i=0;i<=n;i++){
            for(int j=0;j<=m;j++){ 
                if(i&&s1[i]==s3[i+j]) f[i][j]=f[i-1][j];
                if(j&&s2[j]==s3[i+j]) f[i][j]=f[i][j-1]||f[i][j];
            }cout<<endl;
        }
       
        return f[n][m];
    }

 剑指 Offer II 097. 子序列的数目

int numDistinct(string s, string t) {
        if(s.size()==0||t.size()==0||s.size()<t.size()) return 0;
        int n=s.size(),m=t.size();
        s=" "+s,t=" "+t;
        vector<unsigned long long > f(m+1);
        f[0]=1;
     
        for(int i=1;i<=n;i++){
            for(int j=m;j>=0;j--){   
               // f[j]+=f[j];
                if(s[i]==t[j]&&j) f[j]+=f[j-1];
            }
        }
        return f[m];
    }

 剑指 Offer II 098. 路径的数目

int uniquePaths(int m, int n) {
        int f[m][n];
        memset(f,0,sizeof(f));

        for(int i=0;i<m;i++) f[i][0]=1;
        for(int i=0;i<n;i++) f[0][i]=1;

        for(int i=0;i<m;i++){
            for(int k=0;k<n;k++){
               if(i&&k) f[i][k]=f[i-1][k]+f[i][k-1];
            }
        }
        return f[m-1][n-1];
    }

 剑指 Offer II 099. 最小路径之和

int minPathSum(vector<vector<int>>& grid) {
        int n=grid.size(),m=grid[0].size();
        int f[n][m];
        memset(f,0,sizeof(f));
        f[0][0]=grid[0][0];
        for(int i=1;i<n;i++) f[i][0]=f[i-1][0]+grid[i][0];
        for(int i=1;i<m;i++) f[0][i]=f[0][i-1]+grid[0][i];
        for(int i=1;i<n;i++){
            for(int j=1;j<m;j++){
                f[i][j]=min(f[i-1][j],f[i][j-1])+grid[i][j];
            }
        }
        return f[n-1][m-1];
    }

 剑指 Offer II 100. 三角形中最小路径之和

int minimumTotal(vector<vector<int>>& triangle) {
        if(triangle.size()==1) return triangle[0][0];
        int n=triangle.size(),m=n;
        int f[m];
        memset(f,0,sizeof(f));
        f[0]=triangle[0][0];
        int res=INT_MAX;
        for(int i=1;i<n;i++){
            for(int j=i;j>=0;j--){
                if(j!=i) f[j]=f[j]+triangle[i][j];
                else f[j]=f[j-1]+triangle[i][j];
                if(j) f[j]=min(f[j],f[j-1]+triangle[i][j]);
                if(i==n-1) res=min(res,f[j]);
            }
        }

        return res;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值