package com.feng.testproject.algorithm;
import java.util.Arrays;
public class L31 {
public static void main(String[] args) {
int[] nums = {2,3,1,3,3};
nextPermutation(nums);
}
/**
* 如果全是升序在调换最后两位的位置
* 如果全是降序则升序排列
* 以下为有拐点的情形
* 先升后降 132,231 将第一位以及之后所有的数字排序并将首位放大一位的数字
* 先降后升312 调换最后两位的位置
* @param nums
*/
public static void nextPermutation(int[] nums) {
if (nums.length < 2) {
return;
}
if (nums.length == 2) {
int temp = nums[0];
nums[0] = nums[1];
nums[1] = temp;
return;
}
int left = nums[nums.length - 1];
int right = nums[nums.length - 1];
// flag表示true升序 false降序
boolean flag = true;
int equals = -1;
for (int i = nums.length - 2; i > 0; i--) {
int curr = nums[i];
left = nums[i - 1];
right = nums[i + 1];
if (left == curr && curr != right) {
equals = i + 1;
}
if (curr == right && equals != -1) {
right = nums[equals];
}
if (curr <= right && left <= curr) {
flag = true;
} else if (curr >= right && left >= curr) {
flag = false;
} else {
if (curr <= right && left > curr) { // 先降后升
for (int j = nums.length-1; j > 0 ; j--) {
if (nums[j-1] != nums[j]) {
int temp = nums[j-1];
nums[j-1] = nums[j];
nums[j] = temp;
return;
}
}
} else if (curr >= right && left < curr) { // 先升后降
Arrays.sort(nums, i-1, nums.length);
int index = 0;
for (int j = nums.length-1; j > i-1; j--) {
if (left < nums[j]) {
index = j;
}else {
break;
}
}
int temp = nums[index];
for (int j = index; j > i-1; j--) {
nums[j] = nums[j-1];
}
nums[i-1] = temp;
return;
}
}
}
if (flag) { //升序
int temp = nums[nums.length - 2];
nums[nums.length - 2] = nums[nums.length - 1];
nums[nums.length -1] = temp;
} else { //降序
Arrays.sort(nums);
}
}
}
总结
题目给的样例主要是三个数字,刚开始考虑以三个数字为基础的规律浪费了很长时间
不知道有更多的样例是否能总结出 从后往前找第一个降序排序的排列就是要找的答案