日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

每天一道LeetCode-----找到第k个排列

發布時間:2024/4/19 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 每天一道LeetCode-----找到第k个排列 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Permutation Sequence

原題鏈接Permutation Sequence

給定n和k,求[1,2,3,...,n]這個序列的全排列中第k個排列


可以調用k次next_permutation獲取結果,但是next_permutation內部實現比較慢。
首先考慮能不能確定第k個排列是以哪個數字開頭的呢,以[1,2,3,4]的全排列為例,找第14個排列

  • 以1開頭的排列總共有3!個,原因是第一個位置是1,剩下3個位置可以隨便排列,有6個
  • 以2開頭的排列總共有3!個,原因是第一個位置是2,剩下3個位置可以隨便排列,有6個
  • 此時已經有12個排列
  • 所以剩下的兩個排列即第14個排列一定在以3開頭的排列中

用這種方式繼續縮減數量,以3開頭的排列中最小的為[3,1,2,4],3已經固定,那么就找[1,2,4]的全排列的第2個排列,就是整個排列的第14個排列

  • 以1開頭的排列共有2!個,原因是第二個位置是1,剩下2個位置可以隨便排列,有2個
  • 此時已經有兩個排列,可以確定結果一定在以[3,1]開頭的排列中,即[3,1,2,4]或[3,1,4,2]

繼續縮減數量,以[3,1]開頭的排列中最下的為[3,1,2,4],[3,1]已經固定,那么就找[2,4]的全排列的第2個排列,就是[1,2,4]的全排列的第2個排列,也就是整個排列的第14個排列

  • 以2開頭的排列共有1!個,原因是第三個位置是2,剩下一個位置給4,有1個
  • 以4開頭的排列共有1!個,原因是第三個位置是4,剩下一個位置給12,有1個
  • 此時已經有兩個排列,可以確定結果是以4開頭的排列,即[4,2],所以結果為[3,1,4,2]

所以,可以每次確定一個大范圍,在大范圍的基礎上進一步縮小范圍,直到最后只有一個數字為止。遍歷n遍即可。

假設某次需要找到第k個排列(k從1開始),以第i個位置開頭(i從1開始),上述過程可以表示為
要找的排列的開頭是所剩數字中的第k / (n-i)!個 (整除)或第k / (n-i)! + 1個(非整除)數字,(從1開始)

原因
上述第一步,序列為[1,2,3,4],k為14,i為1,(n-i)!為6,k / (n-i)!為2,此時因為要找第14個排列(從1開始),以1,2開頭的各占6個,所以在以3開頭的排列中找,所以應該是k / (n-i)! + 1(非整除),即第3個數字,從1開始,為3
上述第二步,序列為[1,2,3],確定以3開頭后,k為2,i為2,(n-i)!為2,k / (n-i)!為1,此時因為要找第2個排列,以1開頭的就有2個,所以在以1開頭的排列中找,所以應該是k / (n-i)! (整除),即第1個數字,從1開始,為1

上面需要根據情況討論的原因是位置索引都是從1開始的,如果索引從0開始,那么就不會有這么多問題,此時k為14,即要找第13個排列(從0開始)
上述第一步,序列為[1,2,3,4],k為13,i為1,(n-i)!為6,k / (n-i)!為2,k / (n-i)!為2,即第2個數字(從0開始),為3
上述第二步,序列為[1,2,3],確定以3開頭后,k為1,i為2,(n-i)!為2,k / (n-i)!為0,即第0個數字,為1

代碼如下

class Solution { public:string getPermutation(int n, int k) {vector<int> factorial(n+1, 1);for(int i = 2; i <=n; ++i)factorial[i] = i * factorial[i - 1];vector<int> nums;for(int i = 1; i <= n; ++i)nums.emplace_back(i);string res("");for(int i = 1; i <= n; ++i){/* 找開始點 */int index = k / factorial[n - i];/* 如果非整除,加一 */if(k % factorial[n - i] != 0)++index;res += (nums[index - 1] + '0');nums.erase(nums.begin() + index - 1);k = k - ((index - 1) * factorial[n - i]);}return res;} };

總結

以上是生活随笔為你收集整理的每天一道LeetCode-----找到第k个排列的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。