本LeetCode 算法系列文章分类导航:《【LeetCode】 高效算法刷题思路、算法题目分类 - 持续更新》
本文链接: 《【LeetCode #31 题解】 下一个排列》
题目
题目链接:《31. 下一个排列》
实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须原地修改,只允许使用额外常数空间。
以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1
分析思路
这个题可以转换为,寻找下一个比它更大的数。
例如,以 [ 1 , 5 , 8 , 4 , 7 , 6 , 5 , 3 , 1 ] [ 1,5,8,4,7,6,5,3,1] [1,5,8,4,7,6,5,3,1]为例。
-
在 [ 1 , 5 , 8 , ( 4 ) , 7 , 6 , 5 , 3 , 1 ] [ 1,5,8,(4),7,6,5,3,1] [1,5,8,(4),7,6,5,3,1]中,从末尾开始找,找到第一个不是降序非列的数 4 4 4
-
接着在 [ 7 , 6 , ( 5 ) , 3 , 1 ] [ 7,6,(5),3,1] [7,6,(5),3,1]中找到第一个比 4 4 4 更大的数 5 5 5, 交换 5 5 5 和 4 4 4
结果为: [ 1 , 5 , 8 , ( 5 ) , 7 , 6 , ( 4 ) , 3 , 1 ] [ 1,5,8,(5),7,6,(4),3,1] [1,5,8,(5),7,6,(4),3,1] -
最后将 [ 7 , 6 , 4 , 3 , 1 ] [ 7,6,4,3,1] [7,6,4,3,1] 做升序处理,为 [ 1 , 3 , 4 , 6 , 7 ] [ 1,3,4,6,7] [1,3,4,6,7]
-
最终输出结果为 : [ 1 , 5 , 8 , ( 5 ) , 1 , 3 , ( 4 ) , 6 , 7 ] [ 1,5,8,(5),1,3,(4),6,7] [1,5,8,(5),1,3,(4),6,7]
图示动画如下:
c++ 代码实现:
// 示例:
// 1,3,5,8,6,4,2,1
// (1) 从末尾寻找第一个破坏升序的数:5
// (2) 在 8,6,4,2,1 中寻找第一个 大于它的数,6, 交换后的结果 1,3,[6],8,[5],4,2,1
// (3) 将 8,5,4,2,1 按升序排列 ,即 1,2,4,5,8
// (4) 最终结果输出,1,3,[6],1,2,4,[5],8
class Solution {
public:
void nextPermutation(vector<int>& nums) {
// 获得最大长序
int pos = nums.size() - 1;
cout << "数组大小为:"<< pos + 1 << endl;
// 1. 从末尾寻找第一个破坏降序的数
while(pos > 0 && nums[pos] <= nums[pos-1])
pos--;
// 2. 找到第一个比它大的数,交换
if(pos > 0){
cout << "找到数字为: pos="<<pos-1 << " num="<<nums[pos-1] << endl;
for(int i = nums.size()-1 ; i>=pos ; i--){
if(nums[i] > nums[pos-1]){
cout << "交换" <<nums[pos-1] << "和" << nums[i]<< endl;
swap(nums[pos-1], nums[i]);
break;
}
}
}
// 3. 升序排列
reverse(nums.begin() + pos, nums.end());
}
};
提交结果: