31&&60.Next Permutation&&Permutation Sequence (60 Hard)
Next Permutation
Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.
If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).
The replacement must be in-place, do not allocate extra memory.
Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.
1,2,3
→ 1,3,2
3,2,1
→ 1,2,3
1,1,5
→ 1,5,1
题目的意思是:123的全排列按字典顺序为:
123 132 213 231 312 321
如果输入其中某一个序列,返回它的下一个序列。如:输入:213 输出:231 ;输入:321 输出:123
题意寻找比当前排列顺序大的下一个排列。
1)因为降序序列是没法变的更大的,所以从后往前找到第一个升序对的位置。
2)然后就存在调整大小排列顺序的可能,从后往前找到比当前位置大的元素,交换之。
3)当前位置后面的元素还是降序排列,将他们反转得到最小顺序排列。其实就是原来当前位置元素后面是最大的排列,而交换后的新元素之后是最小的排列,他们就是相邻的顺序。
当不存在升序,则当前排列是最大排列,只要旋转整个序列变成最小排列。
算法思想:举例如下
输入:1 4 6 5 3 2
step1:从右往左找到第一个破坏升序(非严格)的元素,此例中为4.记下标为 i
step2: 依然从右往左,找到第一个大于4的元素,此例中5,交换4和5.
step3:从i+1到最右端,逆置。6 4 3 2 to 2 3 4 6
so,1 5 2 3 4 6 即为所求。
class Solution { public: void nextPermutation(vector<int>& nums) { int i,j,len=nums.size(); for(i=len-2;i>=0;--i) { if(nums[i+1]>nums[i]) { for(j=len-1;j>i-1;--j)if(nums[j]>nums[i])break; swap(nums[i],nums[j]); reverse(nums.begin()+i+1,nums.end()); return; } } reverse(nums.begin(),nums.end()); return; } };
Permutation Sequence
The set [1,2,3,…,n]
contains a total of n! unique permutations.
By listing and labeling all of the permutations in order,
We get the following sequence (ie, for n = 3):
"123"
"132"
"213"
"231"
"312"
"321"
Given n and k, return the kth permutation sequence.
Note: Given n will be between 1 and 9 inclusive.
解法参考了:http://blog.csdn.net/lanxu_yy/article/details/17261527
思路:
思路1是用NP的方式来罗列出所有的排列再找出第k个结果,这种方法的时间复杂度与空间复杂度比较高。思路2是研究排序结果的规律,例如取n是,结果可以分为n个组,第一组是第一个数字取最小的那个(即1),第k组是取数字排第k小的那个(即k),每组的数字个数是(n-1)!。依次类推可以递归到n为1时。最终k可以表示为k=A1(n-1)!+A2(n-2)!+...+An,其中Ak代表该数为剩余数字中第Ak小的数字。class Solution { public: string getPermutation(int n, int k) { vector<bool> flag(n,false); int *A=new int[n]; int base=1; for(int i=2;i<n;i++) base*=i; int sum=k-1; for(int i=0;i<n;i++) { A[i]=sum/base; sum=sum%base; if(base!=1) base=base/(n-1-i); } string str; for(int i=0;i<n;i++) for(int j=0;j<n;j++) { if(!flag[j]) { if(A[i]==0) { str.push_back(j+'1'); flag[j]=true; break; } else { A[i]--; } } } return str; } };