lc31 下一个排列
问题:计算整数数组的下一个排列,如果整数数组中的元素按字典顺序排列,下一个排列指当前排列的下一位。
注意点:while条件是查找条件的取反,交换的i-1,k>i-1,注意等号:当降序且相等时一直循环、
//题解:从后往前找到第一个相邻升序的两数[i,j],再找出j后面第一个大于i的数k,交换nums[i]和nums[k],再将j后面的数按升序排列.如果没有这样的两数,则说明整个数组元素为降序,逆置为升序即可
//数组长度
int n = nums.length;
//从后往前找到第一个相邻升序的两数[i-1, i],当降序且相等时一直循环,nums[i-1]>nums[i]
int i=n-1;
while(i>0&&nums[i-1]>nums[i]){i--;}
//找到i之后第一个大于nums[i-1]的数nums[k],i之后的数为降序排列,第一个大的数即为倒序查找后第一个大于nums[i-1]的数.i>0时.当nums[k]<=nums[i-1]时一直循环
int k = n-1;
if(i>0){
while(k>(i-1)&&nums[k]<=nums[i-1]){k--;}
}
//交换nums[i-1]与nums[k],注意交换的是i-1
swap(nums, i-1, k);
//i之后的元素现为降序,逆置为升序,双指针交换.i为0的场景也涵盖了
transfer(nums,i);
//交换两数
public void swap(int[] nums, int a, int b){
int temp=nums[a];
nums[a]=nums[b];
nums[b]=temp;
}
//逆置为升序
public void transfer(int[]nums,int i){
int b=nums.length-1;
while(i<b){
swap(nums, i, b);
i++;
b--;
}
}
==错误解法,只考虑了相邻两位交换位置,没考虑升序相邻后元素的小数,及升序排列
//解法:从后往前依次比较相邻的两个元素,如果后者比前者大就交换下,返回新的数组。如果整个数组遍历完都没返回值,交换下第一位和最后一位
//数组的长度
int n = nums.length;
// 标志变量,表示是否发生元素交换
boolean swapped = false;
//遍历整个数组
for(int i=n-1; i>0; i--){
if(nums[i]> nums[i-1]){
int temp = nums[i];
nums[i] = nums[i-1];
nums[i-1] = temp;
swapped = true;
break;
}
}
// 如果发生元素交换,则不执行后续语句
if (swapped) {
return;
}
//如果第一位元素大于所有元素,将其与最后一位交换
int temp1 = nums[0];
nums[0] = nums[n-1];
nums[n-1]=temp1;
}