Next Permutation

来源:互联网 发布:neon软件图标 编辑:程序博客网 时间:2024/06/08 03:43

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,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

题意:求按字母顺序的比当前排列大的下一个排列。

思路:设数组的长度为n, 对于当前位置j,从后往前扫描从j+1到n-1中间的数字,找到一个最小的但是比nums[j]大的数字,记下下标为idx,将nums[j]和nums[idx]交换,这个时候交换后的新排列肯定是比原排列大的,但是却不是原排列的下一个排列,为了找到下一个排列,需要将j+1到n-1之间数字按照升序排列,这时得到的排列即为原排列的下一个排列。如果对于所有的j都找不到这样的可以交换的数字,也就是原排列是降序的,返回升序后的结果即可。

注:下面的算法1运行时间太长,其实可以简化为算法2。

改进: 同样是为了找到j后面的最小的但是比nums[j]小的元素与nums[j]交换,如果说j到n-1之间都是降序排列的,那么对于j到n-1之间的任意一个数字都不可能找到一个数字在它后面且比自己还大,也就是说j到n-1之间的数字肯定找不到合适的可以和自己交换的数字。

算法描述如下:

  1. 从后往前扫描数组,找到第一个i-1,满足nums[i-1]小于nums[i],也就是说从i-1开始不是降序了,如果找不到这样的i-1,那么说明整个排列是降序的,将原排列转为升序的即可;
  2. 如果找到这样的i-1,说明从i到n-1之间都是降序排列的,那么从后面扫描,找到第一个比nums[i-1]大的数字,肯定是最小的,且比nums[i-1]大的数字,这样的数字一定有,因为nums[i]就是比nums[i-1]还要大的数字。将该数字与nums[i-1]交换即可
  3. 将i-1后面的所有数字按照升序排列
public class Solution {    public void nextPermutation(int[] nums) {       int n=nums.length;       if(n==0 || n==1) return ;       int flag=0;       int idx=-1;       for(int j=n-2;j>=0;j--)       {           int min=nums[j+1];           idx=j+1;           for(int i=j+1;i<n;i++)           {               if(min>nums[i] && nums[i]>nums[j])                {                  min=nums[i];                  idx=i;               }           }          if(idx!=-1 && min>nums[j])          {              int temp=nums[j];              nums[j]=nums[idx];              nums[idx]=temp;              flag=1;              Arrays.sort(nums,j+1,n);              return ;          }       }       if(flag==0)        {           Arrays.sort(nums);           return ;       }    }}

改进后的算法

public class Solution {    public void nextPermutation(int[] nums) {       int n=nums.length;       if(n==0 || n==1) return ;       int i=n-1;       for(;i>=1;i--)       {           if(nums[i]>nums[i-1])             break;       }       if(i==0)         {            Arrays.sort(nums);            return ;        }       for(int j=n-1;j>=i;j--)       {           if(nums[j]>nums[i-1])           {               int temp=nums[j];                   nums[j]=nums[i-1];                   nums[i-1]=temp;               Arrays.sort(nums,i,n);               break;           }       }    }}
0 0