n之中的所有m元素的逆字典序排列組合

問題描述

題目原型大概如下:

學(xué)校要評優(yōu)秀學(xué)生,有十個平時都很優(yōu)秀的學(xué)生,他們之間不相上下,但是評選的名額有限,假設(shè)學(xué)生人數(shù)是n(0<n<=10),評選的名額數(shù)時m(0<m<=n),那么希望隨機從n名學(xué)生中選出m個學(xué)生,并且按字典序的列出所有可能的獲得優(yōu)秀的學(xué)生名額。n個學(xué)生的序號時從 1....n.

示例

輸入:

5 2

輸出:

54
53
52
51
43
42
41
32
31
21

思路

假設(shè)n個學(xué)生的序號是[1,2,...,n],從中選m個學(xué)生,我們生成一個長度為m的數(shù)組,記錄選學(xué)生的序號索引,例如n=5,m=2,那么index=[0,1]是一開始的選擇學(xué)生的索引,index=[n-m,n-m+1]=[3,4]是最后一種情況,這里說明一下如何通過index數(shù)組求出編號,因為開始我們是從最小索引開始,那么用n-index[i] (0<=i<m)就是對應(yīng)的學(xué)生編號,而且恰好能按照字典序由大到小的計算得到學(xué)生序號。

關(guān)鍵是在于index數(shù)組從開始態(tài)到啊結(jié)束態(tài)的不斷變化,其實細心點可以發(fā)現(xiàn),我們每移動一次(相當(dāng)于+1)index末尾元素就可以得到一種選擇的情況,而當(dāng)最后一個元素加一后,其值超過它自己對應(yīng)的最右位置時,我們就需要從最右開始找到與最右元素連續(xù)的索引位置,讓這部分元素的索引從左邊未移動過的最右那個元素的下一個位置開始標(biāo)記自己的索引,而那個左邊未移動過的最右那個元素的索引也開始移動一位,以此往復(fù),知道所有元素的索引位置都到達了自己能到達的最終位置,結(jié)束。

示例:

假設(shè) n = 6,m=3;end=[3,4,5]對應(yīng)m=3個學(xué)生移動的最終索引位置,index=[0,1,2];這是最開始的m=3個學(xué)生的索引位置。

start:

index : 0,1,2

stuno: 1,2,3,4,5,6

index末尾元素到達自己所能到達的最后位置(+1后超出)

index : 0,1, 5

stuno: 1,2,3,4,5,6

下一步的索引變化

index : 0, 2,3

stuno: 1,2,3,4,5,6

再比如

index : 0, 4,5

stuno: 1,2,3,4,5,6

下一步將是

index : 1,2,3

stuno: 1,2,3,4,5,6

最后將是

index : 3,4,5

stuno: 1,2,3,4,5,6

代碼

//注意end index中保存的索引時相對于n來說的范圍時[0,1,...,n-2,n-1]
public void getAllCase(int n,int m){
  if(n<=0 || m<=0 || m>n)
    return;
  int end[] = new int[m];  //選中的m學(xué)生對應(yīng)的末尾索引
  int index[] = new int[m];//當(dāng)前選中的m個學(xué)生的索引值
  //初始化end  和 index
  for (int i = 0; i < m; i++) {
    end[i] = n - m + i;//計算第i個選中的學(xué)生能到達的末尾索引
    index[i] = i; 
  }
  int l = m - 1;//第m個學(xué)生(最后一個學(xué)生)對應(yīng)于m的索引
  while (true) {
    print(index, n, m);
    index[l]++; //每次都是第m個學(xué)生的索引值加一(最后一個)
    if (index[l] > end[l]) { //超過他自己本來只能到達的最大索引,說明需要進行下一輪
      int t = l;
      //找到l位置之前已經(jīng)達到末尾位置的第一個沒有到達對應(yīng)末尾位置的的下標(biāo)
      while (t >= 0 && index[t] >= end[t]) {
        t--;
      }
      //如果t大于等0說明上面while循環(huán)要找到的位置時存在的
      if (t >= 0) {
        int s = index[t];//上一步找到的第一個沒有到達對應(yīng)末尾位置的元素(從右往左)對應(yīng)于n的索引值。
        //從t到m-1除的元素索引加一(相當(dāng)于后移一位,依次排列在t之后,注意:第一次的t位置就已經(jīng)開始加一)
        while (t < m) {
          index[t++] = ++s;
        }
      } else {//否則說明說明位置都已經(jīng)到達末尾,既是所有情況都已經(jīng)遍歷了一次
        break;
      }
    }
  }
}
//根據(jù)當(dāng)前的索引數(shù)組答應(yīng)選中的學(xué)生序號,因為索引數(shù)組時從0開始的,那么n-index[i]恰好得到對應(yīng)的序號
private  void print(int index[], int n, int m) {
  for (int i = 0; i < m; i++) {
    System.out.print(n - index[i]);
  }
  System.out.println();
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 鹿晗和關(guān)曉彤在一起了!?。?鹿晗和關(guān)曉彤在一起了?。?! 鹿晗和關(guān)曉彤在一起了!??! 哎哎哎,兩個高顏值的人在一起了...
    筱筱宇下閱讀 314評論 4 2
  • 天上一輪弦月, 黑漆深幕彎彎掛立, 潛散一池的溫柔明亮。 水中一葉清蓮, 靜靜立于碧波微塘, 簡撐片刻寬廣與陰涼。...
    水木石閱讀 248評論 0 0
  • 前記:由于妞爹只有五天假期和一個周末,回來后還要休息調(diào)整,所以真正出去玩的時間也就五天。最終確定的時間比較晚,只訂...
    Sally99閱讀 309評論 0 1
  • 人生路上有風(fēng)有雨,到處是荊棘叢生,只有我們?nèi)^斗,去拼搏,就一定會有鮮花和掌聲在等待著我們。名人說過,挫折...
    夢想會遠航閱讀 429評論 0 0

友情鏈接更多精彩內(nèi)容