zoukankan      html  css  js  c++  java
  • 面试题: 已知一个含有n个不同元素的集合,要求打印其所有具有k个元素的子集(不允许有重复的)

    TX面试题2: 已知一个含有n个元素的集合,要求打印其所有具有k个元素的子集(不允许有重复的)

    题目分析, 为了便于说明,不妨将问题简化一下:

        已知一个盒子中有n个不同的球,分别标记为{a1,a2,...,an},现在需要从中取出其中任意k个球,求给出各种组合。

    首先,从组合数学的角度,我们可以知道本问题是一个典型的不放回组合问题,总的个数为 c(n,k).

    对于{a1,a2,...,an}中某一个元素 ai是否出现在k元子集中可以把问题分为如下两个子问题。

    (1) 如果ai出现在k元子集中,那么需要在剩下的 n-1个球中选出 k-1个球

    (2) 如果ai没有出现在k元子集中,那么需要在剩下的n-1个球中选出k个球

    既有: c(n,k) = c(n-1,k-1) + c(n-1,k)

    在有该理论的基础上,我们现在的目标就是利用递归调用,当取出的球的个数满足k,则将结果打印即可。

    为了好说明,我们将本问题再次简化一下, 如果已知n元素为连续集合[1,n], 那么递归程序为:

     1 #include <iostream>
     2 #include <cstdio>
     3 using namespace std;
     4 #define N 1000
     5 int a[N]={0}; // 用于存储选中的元素 
     6 int final_k;  // 用于记录k元子集的大小
     7  
     8 /***********************************
     9  * combination 函数中仅使用了a数组,而没有使用辅助数组,
    10  * 这是由于默认原始 N元集合为 {1,2,...,n}。 
    11 ************************************/
    12 void combination(int a[],int n,int k)
    13 {
    14      for(int i=n;i>=k;i--)
    15      {
    16          a[k] = i;
    17          if(k>1)
    18            combination(a,i-1,k-1);  // 不足final_k个元素,递归选取 
    19          else
    20          {
    21              for(int j=a[0];j>0;--j)  // 取出足够多球,打印之 
    22                  printf("%d ",a[j]);
    23              printf("
    ");
    24          }
    25      }
    26 }
    27 
    28 int main()
    29 {
    30     int n,k;
    31     printf("please input n and k: 
    ");
    32     scanf("%d%d",&n,&k);
    33     final_k =k;   
    34     combination(a,n,k);
    35     return 0;
    36 }

    如果是非连续的n个数呢,那么在combination中需要用到辅助数组了:

    tips: 由于LZ我有点懒,所以在输入n个数的时候,默认是不同的数,并没有判断是否有相同的元素。如果大伙儿想去重,请自行添加!

     1 #include <iostream>
     2 #include <cstdio>
     3 using namespace std;
     4 #define N 1000
     5 int a[N]={0};    // 原N元素集合 
     6 int b[N]={0};    // 辅助数组,用于存储当前选取的元素,便于打印 
     7 int final_k;     // 用于记录k元素子集是否满足 
     8 
     9 void combination(int a[],int n,int k)
    10 {
    11      for(int i=n;i>=k;i--)  // 由于是求k元素的组合,所以默认首元素的可能按照数组中顺序有n-k种 
    12      {
    13          b[k] = a[i];  // 将a[i] 放入到数组b中记录 
    14          if(k>1)       // 取出的个数不足final_k个 
    15            combination(a,i-1,k-1); 
    16          else          // 取出足够个数的球,打印结果 
    17          {
    18              for(int j=final_k;j>0;--j)
    19                  printf("%d ",b[j]);
    20              printf("
    ");
    21          }
    22      }
    23 }
    24 
    25 int main()
    26 {
    27     int a[N]={0};
    28     int n,k;
    29     printf("please input n and k: 
    ");
    30     scanf("%d%d",&n,&k);
    31     for(int i=1;i<=n;i++) scanf("%d",&a[i]);  //输入n个不同的元素
    32     final_k =k;   
    33     combination(a,n,k);
    34     system("pause");
    35     return 0;
    36 }
    random sequence

     转载请注明出处:http://www.cnblogs.com/double-win 

  • 相关阅读:
    C++中使用多线程
    hdu 4223 dp 求连续子序列的和的绝对值最小值
    hdu 1372 bfs 计算起点到终点的距离
    hdu 4217 线段树 依次取第几个最小值,求其sum
    心得
    hdu 1175 bfs 按要求进行搜索,是否能到达,抵消两个(相同)棋子
    hdu 4221 greed 注意范围 工作延期,使整个工作时间罚时最少的单个罚时最长的值
    hdu 2844 多重背包 多种硬币,每一种硬币有一点数量,看他能组成多少种钱
    uva LCDDisplay
    hdu 4218 模拟 根据一个圆点和半径画一个圆 注意半径要求
  • 原文地址:https://www.cnblogs.com/double-win/p/3653004.html
Copyright © 2011-2022 走看看