核心思想:双指针
如何判断按照字典序有没有下一个,如果完全降序就没有下一个;
如何判断有没有下一个呢?只要存在a[i] < a[i+1]的升序结构,就有,而且我们应该从右往左找,一旦找到,因为这样才是真正下一个;
当发现a[i] < a[i+1]的结构时,从在[i+1,len)中找到最接近a[i]并且又大于a[i]的数字,由于降序,从右往左遍历即可得到k,然后交换a[i]与a[k],然后对[i+1,len)排序即可,排序只需要首尾不停交换即可。
思路:希望下一个数增加的幅度尽可能的小,这样才满足“下一个排列与当前排列紧邻“的要求。为了满足这个要求,需要:
(1)在尽可能靠右的低位进行交换,需要从后向前查找;
(2)将一个 尽可能小的「大数」 与前面的「小数」交换。比如 123465,下一个排列应该把 5 和 4 交换而不是把 6 和 4 交换;
(3)将「大数」换到前面后,需要将「大数」后面的所有数重置为升序,升序排列就是最小的排列。
class Solution {
public void nextPermutation(int[] nums) {
int left,right;
int len = nums.length;
right = len - 2;
//寻找a[i] < a[i+1]
while(right >= 0){
if(nums[right] < nums[right + 1]){
break;
}
right--;
}
left = right;
right = len - 1;
//寻找最接近的数
while(right >= 0 && left >= 0){
if(nums[right] > nums[left]){
break;
}
right--;
}
int i;
//交换
if(left >= 0){
i = nums[left];
nums[left] = nums[right];
nums[right] = i;
}
//排序输出
for(int j = 1; j <= (nums.length - left) / 2; j++){
i = nums[j + left];
nums[j + left] = nums[--len];
nums[len] = i;
}
}
}