#include <iostream>
#include <vector>
using namespace std;
//分析:观察数列,递减数列找不到比它大的数列(直接跳到4),
// 所以要找到两个递增的元素, 即从右到左找到第一个左边小于右边的元素,
// 让后再找出右边比它大的最小元素,交换二者的位置。
// 然后再将该元素后面的数列逆置。
//思路:1、从右向左搜索,找到后一个数a[i]比它前一个数a[i-1]大的两个数;
// 2、从右向左搜索,找到比a[i-1]大的数中最小的一个,交换位置;
// 3、逆置递增序列,即a[i]~a[end];
// 4、若第一步没找到,直接逆置整个序列
void nextPermutation(vector<int> & v)
{
int end = v.size()-1;
int i = end ,k= end;
while(i)
{
if (v[i]>v[i-1])
break;
--i;
}
if (i>0)
{
--i;
while(v[k]<=v[i])
--k;
swap(v[i],v[k]);
reverse( v.begin()+i+1, v.end() );
}
else
{
reverse( v.begin(),v.end() );
}
}
int main()
{
int a1[3] = {1,2,3};
int a[3] = {3,2,1};
vector<int> v(a,a+3);
auto p =v.begin();
nextPermutation(v);
while ( p!=v.end() )
{
cout<<*p++;
}
return 0;
}
这道题给出一个数列,求大于这个数列的最小数列。
例如:
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1
二、 分析
喜欢使用C++的童鞋或许会马上想到next_permutation()这个库函数,没错,其实这道题就是实现的它(严格说来只是初步实现),如果可以的话,如果直接输入这一行代码就可通过:
1
2
3
|
void
nextPermutation(vector<
int
> &num) {
next_permutation( num.begin(), num.end() );
}</
int
>
|
但是,可不是说我们就这样结束了,当然不能,我们要自己实现它。观察数列会发现,如果数列是递减的话我们是找不出比他更大的数列的,所以我们要找到两个递增元素,即从右到左找到第一个左边小于右边的元素,然后我们再找出该元素右边比他大的最小的元素,交换两数,然后再将该数后面的数列reverse()即可。
分为四步:
1、 从右到左找到第一个左边小于右边的元素num[i];
2、 从右到左找到第一个大于num[i]的元素num[j]
3、 交换num[i]和num[j];
4、 将num[i]后的数列reverse()