leetcode_31:下一个排列

这个题目更像是一个数学题目,是需要分析的。我们知道如果从数字的末尾向前遍历,一直是递增的状态,那么这个数字本身就已经是最大数字了。如下图所示,包括a[i]及后面的数字组合就是最大的,但是遇到了a[i-1],就不是了,所以要从这个a[i-1]下手。

包括a[i-1]及后面的数字组合不是最大的,那么比这个组合大一点的是哪一个呢?我们知道这个a[i-1]是处于高位的(个、十、百、千、万…),所以要找大一点的,就要找在它后面的数组中最后一个比它大的数字(数组是递减的),或者说比它大的数字中最小的,然后交换这两个数字。如下面的两个图所示:

  1. 从7到4变为了递减的关系,说明此时476531不是最大的数了,那么就要找比它大一点的数
  2. 找到了5,然后交换5和4,这时候5后面的数字满足递减关系了,即后面的数字是最大的
  3. 因为5后面的是最大的,只要把后面的逆转,那么就变为了最小的。
  4. 这样就完成了从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;
    }
发布了96 篇原创文章 · 获赞 2 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/reachwang/article/details/103340797