18 m 元素集合的 n 個元素子集

說明:假設有個集合擁有m個元素,任意的從集合中取出n個元素,則這n個元素所形成的可能子集有那些? 

解法:假設有5個元素的集點,取出3個元素的可能子集如下: 

{1 2 3}、{1 2 4 } 、{1 2 5}、{1 3 4}、{1 3 5}、{1 4 5}、{2 3 4}、{2 3 5}、{2 4 5}、 {3 4 5} 

這些子集已經使用字典順序排列,如此纔可以觀察出一些規則: 如果最右一個元素小於m,則如同碼錶一樣的不斷加1 如果右邊一位已至最大值,則加1的位置往左移 每次加1 的位置往左移後,必須重新調整右邊的元素爲遞減順序,所以關鍵點就在於哪一個位置必須進行加1 的動作,到底是最右一個位置要加1 ?還是其它的位置?

 

在實際撰寫程式時,可以使用一個變數 positon來記錄加1 的位置,position的初值設定爲 n- 1, 因爲我們要使用陣列,而最右邊的索引值爲最大 的n- 1,在position位置的值若小於m就不斷加 1 , 如果大於m了,position就減1 , 也就是往左移一個位置; 由於位置左移後, 右邊的元素會經 過調整,所以我們必須檢查最右邊的元素是否小於m ,如果是,則position調整回n- 1,如果不是,則positon維持不變。

***********************程序************************

#include <stdio.h>
#include <stdlib.h>

#define MAX 20

int main(void) {
    int set[MAX];
    int m, n, position;
    int i;

    printf("輸入集合個數 m:");
    scanf("%d", &m);
    printf("輸入取出元素 n :");
    scanf("%d", &n);

    for(i = 0; i < n; i++)
    set[i] = i + 1;
    // 顯示第一個集合
    for(i = 0; i < n; i++)
         printf("%d ", set[i]);
   
    putchar('\n');
    position = n - 1;

    while(1) {
           if(set[n-1] == m){
                position--;
                printf("position=%d\n",position);
           }else{
                position = n - 1;
                printf("position=%d\n",position);
           }
                set[position]++;

         // 調整右邊元素
          for(i = position + 1; i < n; i++)
                 set[i] = set[i-1] + 1;

          for(i = 0; i < n; i++)
                printf("%d ", set[i]);
      
         putchar('\n');

         if(set[0] >= m-n+1)
              break;
      }
    return 0;
}

 

********************END******************

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章