标签:
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
实现下一个排列的功能,就是对数组里的数字进行重新排列,找到所有排列中下一个大于当前数组的排列(按照字典序)。
如果这样的重排不存在,返回最小的那个排列(即对数组进行升序排列)。
所有的操作必须是原址的,也就是不能分配多余的空间。
要找到下一个排列就要找到右边的最短需要排列子串,假设这个最小子串是从I开始的,令字符串为A[N],那么A[I]必须要小于他后面的其中某个元素,那么对A[I]进行替换才会产生更大的排列,否则最小排列可以不包含A[I],那么I就是从右边开始数第一个小于A[I+1]的元素。找到了I之后,那么就要从I后面子串找出一个最小的大于A[I]的数。因为I后面的子串是降序的,所以这里可以使用二分法,也可以使用重载过的lower_bound(虽然这个改进不会对时间复杂度有所影响,但它会减少一次遍历,一共是两次遍历,大概能提高一半的效率)。找到这个数之后,将它与A[I]进行交换,最后再把I之后的数翻转,就是我们要的结果了。时间复杂度是O(N),给出代码如下:
void nextPermutation(vector<int>& nums) { int n = nums.size(); if (n < 2) return; int i = n-2; while (i>=0 && nums[i] >= nums[i+1]) --i; if (i<0) { reverse(nums.begin(), nums.end()); return; } vector<int>::iterator it = lower_bound(nums.begin()+i+1, nums.end(), nums[i], greater<int>()); swap(*(it-1), nums[i]); reverse(nums.begin()+i+1, nums.end()); }
标签:
原文地址:http://www.cnblogs.com/zhiguoxu/p/5469329.html