算法<Next Permutation问题>

此问题描述如下:
给定一个数组,首先从后向前找出最长的递减序列的前一个元素,比如数组{1, 5, 8, 4, 7, 6, 5, 3, 1}中,从后向前最长递减序列是{ 7, 6, 5, 3, 1},这个序列的前一个元素就是4,然后再递减序列中找到最后一个比这个数(4)大的数字(就是5),然后将5与4交换,得到新的数组{1, 5, 8, 5, 7, 6, 4, 3, 1},然后将交换过后的递减序列进行翻转,最后得到的结果就是{1 5 8 5 1 3 4 6 7 }。如果数组单调递减的数组,比如说是{4,3,2,1},则直接翻转就可以得到最终的结果{1,2,3,4}。
注意交换的过程中不能使用额外的空间

如图表示就是:

这里写图片描述

代码实现:

/**
 * @version 2017/7/21.21:33
 */
public class NextPermutation {
    public static void main(String[] args) {
        int[] nums = {1, 5, 8, 4, 7, 6, 5, 3, 1};
        new NextPermutation().nextPermutation(nums);
        for (int num : nums) {
            System.out.print(num + " ");
        }
    }

    public void nextPermutation(int[] nums) {
        if (nums == null || nums.length == 1) {
            return;
        }
        int decreasingElementIndex = getDecreasingElement(nums);
        if (decreasingElementIndex == -1) {
            reverse(nums, 0);
            return;
        }
        swap(nums, decreasingElementIndex, getLastLargeElement(nums, decreasingElementIndex));
        reverse(nums, decreasingElementIndex + 1);
    }

    //获取比第一个数组中从后向前递减的数大的数
    public int getLastLargeElement(int[] nums, int start) {
        int num = nums[start];
        int index = start + 1;
        while (index < nums.length) {
            if (nums[index] > num) {
                start++;
            }
            index++;
        }
        return start;
    }

    //从数组的 某一位置开始反转数组
    public void reverse(int[] nums, int starIndex) {
        int endIndex = nums.length - 1;
        while (starIndex < endIndex) {
            swap(nums, starIndex, endIndex);
            starIndex++;
            endIndex--;
        }
    }

    //从数组的后向前获取第一个递减的数字的下标,比如{1,4,3,2},此时要求的 结果就是0
    public int getDecreasingElement(int[] nums) {
        int lenght = nums.length - 1;
        while (lenght >= 1) {
            if (nums[lenght] > nums[lenght - 1]) {
                return lenght - 1;
            }
            lenght--;
        }
        return -1;
    }

    //交换两个数
    public void swap(int[] nums, int i, int j) {
        if (i != j) {
            nums[i] = nums[i] ^ nums[j];
            nums[j] = nums[i] ^ nums[j];
            nums[i] = nums[i] ^ nums[j];
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值