LeetCode60 第k個排列

2021-08-22 15:02:20 字數 1982 閱讀 9622

給出集合[1,2,3,…,n],其所有元素共有 n! 種排列。

按大小順序列出所有排列情況,並一一標記,當 n = 3 時, 所有排列如下:

"123""132""213""231""312""321"

給定 n 和 k,返回第 k 個排列。

說明:

示例 1:

輸入:n = 3, k = 3輸出:"213"
示例 2:

輸入:n = 4, k = 9輸出:"2314"
從後向前推,比如說 n =  6 ,k = 500:

count陣列來儲存0-6的階乘(其實儲存到5也就是n-1就可以了) 

count : 0  1  2  6  24  120  720

我們要找到1-6全排列從小到大的第50個,數字 1 開始的排列組合有  5!個 數字 2 開始的排列組合有 5!個…… 要找第 500個,那麼第500個數字第一位是  5(120 * 4 < 500  , 120 *  5  > 500),k值需要重置一下, k = k - 120 * 4 = 20; 接著找第二個位置的數字,此時 k = 20,還剩下5個數字進行排列,第二位的數字 以某個數字開始的排列組合有 4!= 24個,k = 20 < 24, 那麼第二位數字應該定位為 當前所剩數字中最小的一位 1,k 值不變繼續為20,找下乙個;第三個位置的數字,以某個數字開始的排列組合有3!個,k = 20 > 6 ,第三位置的數字為 6(6 * 3 = 18 < 20  , 6 *4= 24 > 20 ,注意這裡的4是代表當前數字中未被使用的第4個小的數字,因為1和5都已經使用,所以6為剩下的第四小的數字) ,然後重置一下k = 20 - 6 * 3 = 2,繼續尋找下一位;第四個位置的數字,k = 2 = 2!= 2, 那麼第四個位置的數字為2(目前所剩數字最小的為2,以2打頭的組合有2個,正好k=2),k重置 k = k - (2/2-1)*2 = 2;第五位數字,k=2<1,則第五位數字為4(目前只剩下數字3和4,兩種組合34,43,k=2,取二個組合43) ,之後就按從小到大的順序將剩下的數字依次排到已經排好的數字之後516243

class solution 

return help(n-1,k,flag,count,"");

}public static string help(int index, int k, boolean flag, int count, string string)

return string;

}int yu = k % count[index];// 取餘

//shang 代表取當前數字中第幾小的數字,如果yu!=0的話,記得向前進一

int shang = yu == 0 ? k / count[index] : k / count[index] + 1;

int temp = 0;//temp代表當前位數要取的數字

for (int i = 0; i < shang; temp++)//尋找temp

if (flag[temp] == false)

i ++;

temp --;

string += temp ;

flag[temp] = true;

if (yu == 0)else

}}

**寫的。。很亂。。。

leetcode 60 第k個排列

給出集合 1,2,3,n 其所有元素共有 n 種排列。按大小順序列出所有排列情況,並一一標記,當 n 3 時,所有排列如下 123 132 213 231 312 321 給定 n 和 k,返回第 k 個排列。說明 給定 n 的範圍是 1,9 給定 k 的範圍是 1,n 示例 1 輸入 n 3,k ...

LeetCode 60 第k個排列

給出集合 1,2,3,n 其所有元素共有 n 種排列。按大小順序列出所有排列情況,並一一標記,當 n 3 時,所有排列如下 123 132 213 231 312 321 給定 n 和 k,返回第 k 個排列。說明 給定 n 的範圍是 1,9 給定 k 的範圍是 1,n 示例 1 輸入 n 3,k ...

LeetCode 60 第k個排列

題目鏈結 題解 逆康托展開。考慮康托展開的過程。k v i n i 其中v i 表示在a i 1.n 中比a i 小的數字的個數 也即未出現的數字中它排名第幾 從0開始 那麼我們在逆康托展開的時候,就可以通過直接除 n i 得到每個數字的v i 的值。然後通過給已經出現的數字打tag。剩下的問題就轉...