1. 程式人生 > >第k個排列(C++)

第k個排列(C++)

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

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

  1. "123"
  2. "132"
  3. "213"
  4. "231"
  5. "312"
  6. "321"

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

說明:

  • 給定 n 的範圍是 [1, 9]。
  • 給定 的範圍是[1,  n!]。

示例 1:

輸入: n = 3, k = 3
輸出: "213"

示例 2:

輸入: n = 4, k = 9
輸出: "2314"

【解題思路】

先以n=4,k=9為例,看下圖:

有沒有發現什麼規律?

1.n!種排列中的順序可以分為(n!/n)組,其中每組的第一個數字都一樣;

2.通過k求出該序列落在第幾組,比如,上圖n=4,k=9,就落在第二組,那該序列的第一個元素就是陣列的第二個元素--2;

3.第一個元素確定後,把陣列的這個數摳掉,比如,上面2已經確定了,就把2扣掉,陣列就剩3個元素了---[1,3,4]。注意:摳掉後,陣列仍然要保持有序。

4.當第一個元素確定後,陣列就變成3個元素,k變成了3,即n=3,k=3。陣列為[1,3,4],再重複上面的步驟,就可求出第二個元素是3,在摳掉3。

問題關鍵在於怎麼計算下一次的落在第幾組和k

#include"stdafx.h"
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int getgroup(int num, int k)//num為每個組元素個數;
{
	if (k % num == 0) return k / num;
	else
		return k / num + 1;
}
int getk(int num, int k)
{
	if (k < num) return k;
	else
	{
		if (k % num == 0)
			return num;
		else
			return k % num;
	}		
}
string getPermutation(int n, int k) {
	if (n < 1) return "";
	int count = 1;//n!總共排列數量
	vector<int> vct;
	string res("");
	for (int i = 1; i <= n; i++)
	{
		vct.push_back(i);
	}
	for (int i = 1; i <= n; i++)
	{
		count *= i;
	}
	while (n > 0)
	{
		//每組的個數
		int num = count / n;
		//落在哪一組
		int group = getgroup(num, k);
		//計算下一次的k值
		k = getk(num, k);
		//結果追加到字串
		res += vct[group - 1] + '0';
		//下一次的序列總數
		count /= n;
		//刪除元素
		vct.erase(vct.begin() + group - 1);
		n--;
	}
	return res;
}
int main()
{
	getPermutation(4, 9);
	getPermutation(3, 6);
	getPermutation(3, 1);
	getPermutation(3, 2);
	return 0;
}

解釋一下:

1.n有序數放在vector,主要是刪除指定位置的元素好操作;

2.最核心的是求出group,因為知道group就知道給字串追加哪個數字了,

int getgroup(int num, int k)//num為每個組元素個數;
{
	if (k % num == 0) return k / num;
	else
		return k / num + 1;
}

舉例:n=4,k=9

count = 24,共n=4組,每組num=6個序列,第9個應該落在 第(9 / 6+1)=2組上,所以就把當前陣列[1,2,3,4]的第二個(2)數追加到字串上,然後把 "2"從陣列中去掉陣列變為[1,3,4].

需要注意的是:k能被num整除時是特殊處理,比如上面的例子(n=4,k=12)那麼group=12/2=2,就是在第二組,不需要加1了。

還有這裡k不會等於0,所以不用考慮k=0的情況。

3.本次的值追加到字串後,就需要計算下一次k的值

int getk(int num, int k)
{
	if (k < num) return k;
	else
	{
		if (k % num == 0)
			return num;
		else
			return k % num;
	}		
}

如上圖,從n=4,k=9 變為 n=3,k=3;這是怎樣一個過程?