• 全排列,组合问题


    包括了排列,组合,子集问题,子集带重复问题,基本全了,就差在看看leetcode以前怎么写的了

      1 //全排列的两种方法
      2 #include <iostream>
      3 #include <vector>
      4 #include <algorithm>
      5 using namespace std;
      6 
      7 //方法一,采用swap方法
      8 void quanpailie(char * A,int first,int n)
      9 {
     10     if(A==NULL)
     11     {
     12         cout<<"A is NULL"<<endl;
     13         return;
     14     }
     15     if(n<=1)
     16     {
     17         cout<<A<<endl;
     18         return;
     19     }
     20     for(int i=first;i<first+n;i++)
     21     {
     22         swap(A[i],A[first]);
     23         quanpailie(A,first+1,n-1);
     24         swap(A[i],A[first]);
     25     }
     26     return;
     27 }
     28 
     29 //采用字典序全排序,就是采用的字典排序思想,从后向前找出第一个A[i]<A[i+1],如果没有就说明结束,
     30 //然后在从右向左找出第一个大于A[i]的,进行交换,然后逆序i+1到最后(也就是逆序j到最后)。
     31 void quanpailie2(char * A,int n)
     32 {
     33     cout<<A<<endl;              //输出最开始的“abc”
     34     if(A==NULL||n<=0)
     35         return;
     36     while(true)
     37     {
     38         int i;
     39         for(i=n-2;i>=0;i--)
     40         {
     41             if(A[i]<A[i+1])
     42                 break;
     43         }
     44         if(i<0)
     45         {
     46             break;
     47         }
     48         for(int k=n-1;k>=0;k--)
     49         {
     50             if(A[k]>A[i])
     51             {
     52                 swap(A[i],A[k]);
     53                 break;
     54             }
     55         }
     56         reverse(A+i+1,A+n);
     57         cout<<A<<endl;
     58     }
     59 }
     60 
     61 /*
     62 子集问题,子集问题有两种情况,比如正常的{1,2,3}求子集就是{},{1},{2},{3},{1,2},{1,3},{2,3},{1,2,3}
     63 还有就是有重复的情况比如{1,2,2}求子集就是{},{1},{2},{1,2},{2,2},{1,2,2}
     64 注意区分子集问题和组合问题,组合问题为最简单的递归回溯问题1,2,3,4,选2个为{1,2},{1,3},{1,4},{2,3},{2,4},{3,4},{3,4}
     65 */
     66 
     67 //组合问题(子集问题),方法一,采用vector,比较取巧,完全不计较空间的解法了,这个是全组合问题给你abc返回
     68 //{},{a},{b},{c},{a,b},{a,c},{b,c},{a,b,c},注意和C(n,k)的区别
     69 //最简单情况,没有重复的方法一,{1,2,3}
     70 void subsets(char *A ,int n,vector<vector<char>> &result)
     71 {
     72     vector<char> tmp;                            //空vector
     73         result.push_back(tmp);
     74     for(int i=0;i<n;i++)
     75     {
     76         int size=result.size();                //注意,必须提前村上size,不然每次result.size()都是新的
     77         for(int j=0;j<size;j++)
     78         {
     79             vector<char> t=result[j];         //必须用个临时的新的,否则会更改result[j]的值。
     80             t.push_back(A[i]);                //注意是push_back(A[i])
     81             result.push_back(t);
     82         }
     83     }
     84     //最后result里面有一个空的
     85     //result.erase(result.begin());  //或者不删除也行,在显示的时候也可以不显示,但会多打出一个换行符
     86     /*for(int i=0;i<result.size();i++)
     87     {
     88         for(int j=0;j<result[i].size();j++)
     89         {
     90             cout<<result[i][j];
     91         }
     92         cout<<endl;
     93     }*/
     94 }
     95 
     96 //子集问题,方法二,采用递归方法,也是普通的{1,2,3,4}
     97 void subsets2(char *A,int n,int first,vector<vector<char>> &result,vector<char> &tmp)
     98 {
     99     result.push_back(tmp);
    100     for(int i=first;i<n;i++)
    101     {
    102         tmp.push_back(A[i]);
    103         subsets2(A,n,i+1,result,tmp);
    104         tmp.pop_back();
    105     }
    106 
    107 }
    108 
    109 
    110 //子集问题,特殊的情况处理如{1,2,2}这种情况的子集,方法一,也是迭代方法,只不过加了去重的思想
    111 
    112 void subsets_without_repeat(char *A ,int n,vector<vector<char>> &result)
    113 {
    114     sort(A,A+n);//注意必须先排序
    115     vector<char>tmp;
    116     result.push_back(tmp);
    117     int size,pre_size,j;
    118     for(int i=0;i<n;i++)
    119     {
    120         size=result.size();
    121         if(i-1>=0&&A[i]==A[i-1])             //如果重复了,就让j是从上次的size开始,注意初始判断i-1>=0
    122             j=pre_size;
    123         else
    124             j=0;
    125         while(j<size)
    126         {
    127             vector<char> t=result[j];
    128             t.push_back(A[i]);
    129             result.push_back(t);
    130             j++;
    131         }
    132         pre_size=size;                    //记录上次的size
    133     }
    134 }
    135 
    136 /*子集问题,特殊的情况处理如{1,2,2}这种情况的子集,方法二,也是采用递归方法,只不过加了去重的思想,去重的思路是{1,2,2},
    137 当是{},{1},{1,2},{1,2,2},tmp原来是{1,2},然后弹出2,tmp是{1},下一个元素是第二个2时,这个就可以跳过了,不用再有{1,2}了,然后1弹出
    138 2入为{2},即i!=first&&A[i]==A[i-1]就可以跳过了
    139 */
    140 void  subsets_without_repeat2(char *A,int n ,int first,vector<vector<char>> & result,vector<char> & tmp)
    141 {
    142     result.push_back(tmp);
    143     for(int i=first;i<n;i++)
    144     {
    145         if(i!=first&&i-1>=0&&A[i]==A[i-1])
    146             continue;
    147         tmp.push_back(A[i]);
    148         subsets_without_repeat2(A,n,i+1,result,tmp);
    149         tmp.pop_back();
    150     }
    151 }
    152 
    153 
    154 /*
    155 组合问题,C(n,k)问题,很容易,用递归回溯的典型,1,2,3,4 ,给定n为4,k=2,则{1,2},{1,3},{1,4},{2,3},{2,4},{3,4}
    156 */
    157 void compose(char *A,int n,int start,int dep,vector<vector<char>> &result,vector<char> &tmp)
    158 {
    159     if(A==NULL||n<=0)
    160         return;
    161     if(dep==2)
    162     {
    163         result.push_back(tmp);
    164         return;
    165     }
    166     for(int i=start;i<n;i++)
    167     {
    168         tmp.push_back(A[i]);
    169         compose(A,n,i+1,dep+1,result,tmp);
    170         tmp.pop_back();
    171     }
    172 }
    173 
    174 int main()
    175 {
    176     char A[]="1234";
    177     vector<vector<char>> result;
    178     vector<char> tmp;
    179     //quanpailie(A,0,4);
    180     //quanpailie2(A,4);
    181     //subsets(A,3,result);
    182     //subsets2(A,4,0,result,tmp);
    183     //subsets_without_repeat(A,3,result);
    184     //subsets_without_repeat2(A,3,0,result,tmp);
    185     compose(A,4,0,0,result,tmp);
    186     for(int i=0;i<result.size();i++)
    187     {
    188         for(int j=0;j<result[i].size();j++)
    189         {
    190             cout<<result[i][j];
    191         }
    192         cout<<endl;
    193     }
    194     system("pause");
    195 }
  • 相关阅读:
    【Android-功能】Android应用增量更新
    【android-音视频】listview中播放音频,实现音频时长的倒计时,暂停,切换。
    Mysql中的DQL查询语句
    DDL、DML和DCL的理解
    WIN2000 XP 2003系统密码破解方法
    ASP.NET开发学习视频教程大全(共800集)
    VS2010中,无法嵌入互操作类型“……”,请改用适用的接口的解决方法
    正则表达式-RegExp-常用正则表达式
    20151216
    20151124-数据类型
  • 原文地址:https://www.cnblogs.com/zmlctt/p/3848115.html
Copyright © 2020-2023  润新知