实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须原地修改,只允许使用额外常数空间。
以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1
方法:扫描法
思路:
1,首先要找到满足条件的数组索引,例如:1,4,5,7,6,3
2,从数组的最后一个元素开始找,直到找到索引i,i处的元素比i + 1 处的元素小 ,那么就找到了!就是5这个元素位置,也就是 i = 2;
3,然后拿着这个位置的元素,从数组的最后一个位置开始找比他小的元素,就是3所在的位置5;
4,然后换位数组变成1,4,3,7,6,5 ,并且需要对数组i位置右边的元素进行升序排列,也就是i=3,也就是7这个元素除;
5,重新排序在此题中很简单,因为右边的元素是从i+1到length-1是降序,我们需要从i+1处开始到length-1是升序,所以只需要将元素头尾对应元素互换位置即可;
class Solution {
public void nextPermutation(int[] nums) {
int end = nums.length - 2;
//有则换位,有半段重拍,无则升序全部重拍
while (end >= 0 && nums[end + 1] <= nums[end])
end --;//记录刚好满足条件的索引位置
if (end >= 0) {
int temp = nums.length - 1;
while (temp >= 0 && nums[temp] <= nums[end] )
temp --; //找到换位点
swap(nums, end, temp);
}
//换位后对end位之后的数组进行重排序(没有换位则刚好全部升序排列)
reverse(nums, end + 1);
}
//重排序
private void reverse(int[] nums, int start) {
int end = nums.length - 1;
while (start < end) {//两两换位,头尾
swap(nums, start, end);
start ++;
end --;
}
}
//换位
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
注意:对符合目标元素索引的记录,以免出错;以及对while循环的使用。