[LeetCode]31.nextPermutation

来源:互联网 发布:nginx 配置http2 编辑:程序博客网 时间:2024/06/03 16:23
题目: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

        题意是找到全排列的下一个序列;需要理解什么全排列:给定n个数(1~n),所有n个数的排列组合,共有n!种
如果全排列根据字典顺序来排序,那么它的下一个序列是唯一的。
按照字典顺利进行排列的算法需要了解:字典顺序是按照字母升序排列,如果是一个单词,那么后一个单词字符串大小大于前一个。
当对一组整数求它的下一个序列时,我们要考虑最后一个排列n...321的下一个序列应该是123...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-1  Pk   Pn…Pk+1PjPk-1…Pj+1即P的下一个。
小例子:
原序列:    6 8 7 4 3 2
step 1         6 8 7 4 3 2
step 2         6 8 7 4 3 2
step 3         7 8 6 4 3 2
step 4      将8 6 4 3 2 翻转,最终结果:    7 2 3 4 6 8
1、从右向左找到第一个非递增元素,      j=max{i|Pi<Pi+1} 得j=0;即6
2、从右向左找到第一个大于6的元素,   k=max{i|Pi>Pj}    得 k=2;即7 
3、将6与7置换                                            交换位置0和2元素

4、将6后的元素反转                                  将位置j+1后的元素翻转

代码如下:

class Solution {public:void nextPermutation(vector<int>& nums) {int k = -1;for (int i = nums.size() - 2; i >= 0; i--) {if (nums[i] < nums[i + 1]) //从右向左找到第一个降序的索引k{k = i;break;}}if (k == -1)//如果从右到左全是升序将整个序列翻转{reverse(nums.begin(), nums.end());return;}int L = -1;for (int i = nums.size() - 1; i > k; i--){if (nums[i] > nums[k])//从右向左找到第一个大于num[k]的索引L{L = i;break;}}swap(nums[k], nums[L]);//交换reverse(nums.begin() + k + 1, nums.end());//将k+1之后的序列翻转}};

其实STL中有相应的库函数next_permutation,介绍如下:

      C++ STL中提供了next_permutation与prev_permutation可以获取数字或者是字符的全排列,其中std::next_permutation提供升序、prev_permutation提供降序。

1.std::next_permutation函数原型

  template <class BidirectionalIterator>

  bool next_permutation (BidirectionalIterator first, BidirectionalIteratorlast );

  template <class BidirectionalIterator, classCompare>

  bool next_permutation (BidirectionalIteratorfirst,BidirectionalIterator last, Compare comp);

       说明:next_permutation,重新排列范围内的元素[first,last)返回按照字典序排列的下一个值较大的组合。注意不包含last,last指向最后元素的下一个位置。

返回值:如果有一个更高的排列,它重新排列元素,并返回true;如果它已经是最大排列,它按升序排列重新元素,并返回false。

例子“:

// next_permutation#include <iostream>#include <algorithm>using namespace std;int main () {  int myints[] = {1,2,3};  cout << "The 3! possible permutations with 3 elements:\n";  sort (myints,myints+3);  do {    cout << myints[0] << " " << myints[1] << " " << myints[2] << endl;  } while ( next_permutation (myints,myints+3) );  return 0;}

输出:

1 2 3  1 3 2  2 1 3  2 3 1  3 1 2  3 2 1

2.std::prev_permutation函数原型

template <classBidirectionalIterator>

 bool prev_permutation (BidirectionalIterator first,

                         BidirectionalIteratorlast );

template <class BidirectionalIterator,class Compare>

 bool prev_permutation (BidirectionalIterator first,

                         BidirectionalIteratorlast, Compare comp);

说明:prev_permutation,重新排列范围内的元素[first,last)返回按照字典序排列的下一个值较小的组合。注意不包含last,last指向最后元素的下一个位置。

返回值:如果有一个更小的排列,它重新排列元素,并返回true;如果已经是最小排列,它按降序排列重新元素,并返回false。

例子:

// prev_permutation#include <iostream>#include <algorithm>using namespace std;int main () {  int myints[] = {1,2,3};  cout << "The 3! possible permutations with 3 elements:\n";  sort (myints,myints+3);  reverse (myints,myints+3);  do {    cout << myints[0] << " " << myints[1] << " " << myints[2] << endl;  } while ( prev_permutation (myints,myints+3) );  return 0;}

Output:

3 2 1  3 1 2  2 3 1  2 1 3  1 3 2  1 2 3