面試中關於排列的題目還是蠻常見的,之前有個同學面百度,就遇到了一個排列題目,分享一下。
題目描述:
給你一個數組,如果是按照數字的大小排序,那麼請你輸出當前數組的下一個排列是什麼
例如, 下面的數據,就是按照排列序生成的四組數據。
3 1 2 4 5
3 1 2 5 4
3 1 4 2 5
3 1 4 5 2
雖然有個函數叫next_permutation, 不過做OJ還好,面試這個一定不行啦,所以還是自己分析一下。
分析:
我們用字典序的排列生成方法:
生成給定全排列的下一個排列
所謂一個的下一個就是這一個與
下一個之間沒有其他的。這就要求這一個與下一個有盡可能長的共同前綴,也即變化限制在盡可能短的後綴上。
算法分三個步驟:
一般而言,設P是[1,n]的一個全排列。
1. P=P1P2…Pn=P1P2…Pj-1PjPj+1…Pk-1PkPk+1…Pn
j=max{i|Pi<Pi+1},k=max{i|Pi>Pj}
2. 對換Pj,Pk,將Pj+1…Pk-1PjPk+1…Pn翻轉,
3. P’= P1P2…Pj-1PkPn…Pk+1PjPk-1…Pj+1即P的下一個。
代碼如下:
- Memory: 168K Time: 469MS
- Language: C++ Result: Accepted
- Source Code
- #include<stdio.h>
- #include <memory.h>
-
- void swap( int &a, int &b)
- {
- a = a ^ b;
- b = a ^ b;
- a = a ^ b;
- }
-
-
- bool GetNextPermutation(int a[], int size)
- {
- int m = size - 1;
- int i,j;
- while(m > 0 && a[m-1] > a[m]) // step 1
- {
- m--;
- }
-
- //in this case, the current permutation is the last
- if(m == 0) //
- {
- for( i = 0, j = size - 1; i < j; i++, j--)
- {
- swap(a[i], a[j]);
- }
- return false;
- }
-
- for( j = size - 1; j > m - 1; j--)//step 2
- {
- if(a[j] > a[m-1])
- {
- swap(a[j], a[m-1]);
- break;
- }
- }
-
- for( i = m, j = size - 1; i < j; i++, j--)//step 3
- {
- swap(a[j], a[i]);
- }
- return true;
- }
-
- void printArray(int a[], int size)
- {
- int i;
-
- for( i = 0; i < size; i++)
- {
- if( i == 0)
- {
- printf("%d", a[i]);
- }
- else
- {
- printf(" %d", a[i]);
-
- }
- }
- printf("\n");
- }
- int main()
- {
- int nSize;
- int a[1024];
- int ncase;
-
- scanf("%d", &ncase);
- int n,k;
- while(ncase--)
- {
- scanf("%d%d", &n, &k);
-
- for( int i = 0; i < n; i++)
- {
- scanf("%d", &a[i]);
- }
-
- while(k--)
- {
- GetNextPermutation(a, n);
-
- }
- printArray(a, n);
-
- }
- return 0;
- }