https://leetcode.com/problems/next-permutation/
O(n), O(1)
http://bangbingsyb.blogspot.com/2014/11/leetcode-next-permutation.html?m=1
從右到左找到第一個非升序的 index (pivot), (若找不到代表已經是最大排序, 要直接 reverse)
找到後再從右到左, 找到比 nums[pivot] 大的元素
https://www.cnblogs.com/grandyang/p/4428207.html
[[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]]
如果给定数组是 "降序",则说明是全排列的最后一种情况,则下一个排列就是最初始情况
題目要的是 lexicographically next greater permutation of numbers
邏輯的思考, 我不可能改第一位, 如果想要大一點點, 會想從最低位開始, 但改了最低位, 其他位必定也要調整
假設是 1~5
[ ] 4321 => 這狀況下, 後面都已經是最大了, 如果想要更大就要去動到前面的部分了
[ ] 4 5321
class Solution {
public void nextPermutation(int[] nums) {
int pivot = findNonDescendingIndex(nums) - 1;
if (pivot != -1) {
int swapIndex = findGreaterThanPivot(nums, pivot);
swap(nums, pivot, swapIndex);
}
reverse(nums, pivot+1);
}
private int findNonDescendingIndex(int[] nums) {
for (int i = nums.length - 1 ; i > 0 ; i--) {
if (nums[i] > nums[i-1]) {
return i;
}
}
return 0;
}
private int findGreaterThanPivot(int[] nums, int p) {
for (int i = nums.length - 1; i >= p ; i --) {
if (nums[i] > nums[p]) {
return i;
}
}
return -1;
}
private void swap(int nums[], int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
private void reverse(int nums[], int s) {
int e = nums.length - 1;
while(s < e) {
swap(nums, s++, e--);
}
}
}
new version
class Solution {
public void nextPermutation(int[] nums) {
int pivot = findPivot(nums);
if (pivot == 0) {
reverse(0, nums);
} else {
pivot = pivot-1;
int swapTarget = findSwapTarget(nums, pivot);
swap(nums, pivot, swapTarget);
reverse(pivot+1, nums);
}
}
private int findSwapTarget(int[] nums, int pivot) {
for (int i = nums.length-1; i > pivot; i--) {
if (nums[i] > nums[pivot]) {
return i;
}
}
return -1;
}
// 34321
private int findPivot(int[] nums) {
for (int i = nums.length - 1; i >= 1; i--) {
if (nums[i] > nums[i-1]) {
return i;
}
}
return 0;
}
private void swap(int[] nums, int left, int right) {
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
}
private void reverse(int start, int[] nums) {
System.out.println(start);
int left = start;
int right = nums.length - 1;
while (left < right) {
swap(nums, left, right);
left++;
right--;
}
}
}
/*
4 521
swap
5 421 => 然後後面當然要最小的狀況, 所以做 reverse
=>
5 124
ex:
[3] 8642 => 後面這部分不能在改動了, 因為無法更大, 由低位到高位是升序
所以就會打前面的主意
3 跟 後面比他大的交換(剛好大一點的, 也就是從低位 2, 4, ...
so 3 and 4 swap,
4 8632 => 後面在 reverse
4 2368
少動高位
1. find ascding order from last
2. if index numk not , swap this numk with the first number larger than numk (between numk+1 to end)
3. swap
4. reverse rest number (between numk+1 to end), because we want smallest one in the rest part
ex:
[3] 8642
4 8632
4 2368
*/