实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列(即组合出下一个更大的整数)。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须原地修改,只允许使用额外常数空间。
示例 1:
输入:nums = [1,2,3]
输出:[1,3,2]
示例 2:
输入:nums = [3,2,1]
输出:[1,2,3]
示例 3:
输入:nums = [1,1,5]
输出:[1,5,1]
示例 4:
输入:nums = [1]
输出:[1]
1.自己的解法:关键就是在右边找到一个较小数,然后在这个较小数的右侧找一个比它大的较大数,将两个数交换位置,然后将较小数位置的右侧子数组进行升序排序,得到的就是下一个排列。
class Solution {
public void nextPermutation(int[] nums) {
int index1 = nums.length - 2;
while(index1 >= 0 && nums[index1] >= nums[index1 + 1]){//找到第一个左边小于右边的较小数
index1--;
}
if(index1 >= 0){//说明数组不是降序排列的
for(int index2 = nums.length - 1;index2 >= 0;index2--){
//找到较小值右边的第一个大于它的值,交换位置,然后对后面的元素以升序顺序排列
if(nums[index2] > nums[index1]){
int temp = nums[index1];
nums[index1] = nums[index2];
nums[index2] = temp;
Arrays.sort(nums,index1 + 1,nums.length);
return;
}
}
}
Arrays.sort(nums);
}
}
2.答案解法:可以找到规律发现交换位置后右侧子数组的排列其实是逆序的,因此就不需要使用排序算法了,这个地方可以进行优化。
class Solution {
public void nextPermutation(int[] nums) {
int i = nums.length - 2;
while (i >= 0 && nums[i] >= nums[i + 1]) {//找到较小数
i--;
}
if (i >= 0) {
int j = nums.length - 1;
while (j >= 0 && nums[i] >= nums[j]) {//从末尾开始向左找到第一个大于较小数的值
j--;
}
swap(nums, i, j);//交换较小数和较大数的位置
}
reverse(nums, i + 1);//对较小数下标后面的子数组进行逆序处理,最终得到下一数列
}
//交换位置
public void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
//逆序
public void reverse(int[] nums, int start) {
int left = start, right = nums.length - 1;
while (left < right) {
swap(nums, left, right);
left++;
right--;
}
}
}
题源:力扣