这个题目更像是一个数学题目,是需要分析的。我们知道如果从数字的末尾向前遍历,一直是递增的状态,那么这个数字本身就已经是最大数字了。如下图所示,包括a[i]及后面的数字组合就是最大的,但是遇到了a[i-1],就不是了,所以要从这个a[i-1]下手。
包括a[i-1]及后面的数字组合不是最大的,那么比这个组合大一点的是哪一个呢?我们知道这个a[i-1]是处于高位的(个、十、百、千、万…),所以要找大一点的,就要找在它后面的数组中最后一个比它大的数字(数组是递减的),或者说比它大的数字中最小的,然后交换这两个数字。如下面的两个图所示:
- 从7到4变为了递减的关系,说明此时476531不是最大的数了,那么就要找比它大一点的数
- 找到了5,然后交换5和4,这时候5后面的数字满足递减关系了,即后面的数字是最大的。
- 因为5后面的是最大的,只要把后面的逆转,那么就变为了最小的。
- 这样就完成了从
4+最大
到5+最小
的变化,这也是最核心的思路。
最后贴上自己写的代码:
public void nextPermutation(int[] nums) {
if (nums.length == 0 || nums.length == 1)
return;
int numLength = nums.length;
int index = numLength - 1; //指向第一个从后向前非递增的元素下标
for (; index > 0; --index) {
if (nums[index-1] < nums[index]) {
index--; //index是较后元素,所以需要减1
break;
}
}
//本身就是个最大的数了,直接倒置整个数组
if (index == 0 && nums[index] > nums[index+1]) {
for (int head = 0, tail = numLength-1; head < tail; ++head, --tail) {
swap(nums, head, tail);
}
return;
}
int swapIndex = index + 1; //找到后面比它大的数字中最小的那个,也就是位置靠后的那个
for (; swapIndex < numLength && nums[swapIndex] > nums[index]; ++swapIndex);
swapIndex--;
swap(nums, index, swapIndex); //找到后,交换两者
//再将后面的最大数字进行整个的逆转,就可以了
int head = index + 1, tail = numLength-1;
while (head < tail) {
swap(nums, head, tail);
head++;
tail--;
}
}
//交换数组中两个指定下标的数字
public void swap(int[] nums, int index1, int index2) {
int temp = nums[index1];
nums[index1] = nums[index2];
nums[index2] = temp;
}