每日一道编程题——求比当前数值大的新排列

来源:互联网 发布:socket网络编程视频 编辑:程序博客网 时间:2024/06/05 04:59

求比当前数值大的新排列

题目

Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.

If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).

The replacement must be in-place, do not allocate extra memory.

Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.

1,2,3 → 1,3,23,2,1 → 1,2,31,1,5 → 1,5,1

分析

给出一个数组,以当前数组的元素顺序组成一个整数,我们要从新排列这个数组,使得新的整数比当前的整数大,且新的整数只能是当前整数的相邻值,即新的整数与现在的整数之间无法插入别的排列值。
若无法找到满足上面条件的排列,那么将数组排从小到大排列即可。
例如:
1,2,3 我们能够排列出1,3,22,1,32,3,1等等,但是结果是1,3,2,因为132是比123大的最小的组合(213,231都比132大)。

算法

  1. 暴力求解:列出所有的排列组合,然后与原来的比较,这种办法的时间复杂度是n!,是一个非常差的时间复杂度。
  2. 利用规律求解。
    例如:1,2,3,6,5,4,3,2
    对于正整数而言,我们只要尽量变大低位,因为低位的变化对数值的增加较小,所以更接近答案。
    我们可以从最右边开始向前比较,如果后一个数大于前一个数,那么我们要从后面的数里面找出一个数替换前一个数(即nums[i]>nums[i-1])。
    在这个例子里面,我们发现6>3,所以我们要替换掉3,那用几替换呢?当然是用比3大的最小的数,那么无疑就是4了,交换3和4,得到 :1,2,4,6,5,3,3,2 这样就得到了比原来大的整数了,改低位比改高位得到的数小得多,那么还没完,我们发现在交换数之前,与交换之后,后面的数都是从大到小排列的,我们要对后面的数进行从小到大排序,只需要逆序就可以了,逆序之后:1,2,4,2,3,3,5,6
    这样就得到了满足题目的要求了。
    如图所示:
    算法图解
  3. 代码
public class Solution {    public void nextPermutation(int[] nums) {        int len = nums.length;        int index = 0;        if(len==1) return;        for(int i =len-1;i>=1;i--){            if(nums[i]>nums[i-1]){                //返回比num[i-1]大的最小的数下标                index = indexOfBigNum(nums,nums[i-1],i);                //交换                int temp = nums[i-1];                nums[i-1] = nums[index];                nums[index] = temp;                index = i;//记录交换的下标                break;            }        }        //从index开始后面的数变为逆序 若无交换则从0开始逆序        reverse(nums,index);    }    public void reverse(int[] nums,int start){        int len = nums.length;        for(int i=0;i<(len-start)/2;i++){            int temp = nums[i+start];            nums[i+start] = nums[len -1 -i];            nums[len-1-i] = temp;        }    }    public int indexOfBigNum(int[] nums,int target,int start){        for(int i =start;i<nums.length;i++){            if((i<nums.length-1 && nums[i]>target && nums[i+1]<=target) || (i == nums.length-1 && nums[i]>target)){                return i;            }        }        return start;    }}

这个时间复杂度只有O(n)

0 0
原创粉丝点击