2023.5.20
题目描述:
理解题目意思都花了10几分钟.... 半天没有想到什么好解的办法,直接移步评论区,扫了几眼别人的思路,回来自己敲代码,第一遍通过50多例,优化了一下代码,第二遍通过200多例,但还是出错。 总是有些情况没考虑到,真的崩溃...
最后没辙了,去看了下别人的代码,虽然代码看懂了,但我感觉我一辈子自己都想不出来这样的代码... 下面附上自己手敲的代码,希望几个月后回来这道题我能自己想出来。
class Solution
{
public:
void nextPermutation(vector<int>& nums)
{
int n = nums.size();
int i = n-1;
int j = i-1;
int k = n-1;
while(j >= 0 && nums[i] <= nums[j])
{
j--;
i--;
}
if(j >= 0)
{
while(nums[k] <= nums[j])
{
k--;
}
swap(nums[j] , nums[k]);
}
sort(nums.begin()+j+1 , nums.end());
}
};
感觉这道题没有什么技巧性,就是思路很新奇,很难想,只要求自己笔试遇到一样的题能做出来就行。
2023.9.25
时隔四个月,二刷。 本题思路有两个关键点:①下一个排列需要比当前排列大②下一个排列和当前排列的差值需要尽可能小。 直观思路是从数组后面选一个大数和前面的小数交换,这样可以满足第一个条件,但是第二个条件则需要加一些限制。 具体步骤如下:
从后往前遍历,找到第一个升序的对组,如数组[1,2,3,8,5,7,6,4],从后往前找第一个升序对组是[5,7],将5的索引记录下来,放入变量start中。此时7往后的数字肯定都是降序的,再从后往前找到第一个大于5的数字,这个数是大于5的数字中最小的那一个,即6,将该数的索引放入变量index中。 将两个数交换,得到[1,2,3,8,6,7,5,4],再将start往后的数组排序。 这样做就可以保证下一个排列是大于当前排列、且幅度最小的排列了。
代码如下:
class Solution {
public:
void nextPermutation(vector<int>& nums) {
int start=0;
//从右往左 找到第一对 升序对组 靠左的那个数start。
for(int i=nums.size()-2; i>=0; i--)
{
if(nums[i] < nums[i+1])
{
start = i;
break;
}
}
int index = 0;
//从右往左 找到大于start的数中 最小的那一个
for(int i=nums.size()-1; i>start; i--)
{
if(nums[i] > nums[start])
{
index = i;
break;
}
}
//数组是降序的情况:直接反转
if(start == index)
{
reverse(nums.begin(),nums.end());
return;
}
swap(nums[start],nums[index]);
sort(nums.begin()+start+1,nums.end());
}
};