一,问题描述
1 ,实现”下一个排列“函数,将排列中的数字重新排列成字典序列中的下一个更大的排列。如果这样的重新排列是不可能的,它必须重新排列成可能的最低顺序(即升序排序)
重排必须在原地,不分配额外的内存。
以下是一些示例,左侧是输入,右侧是输出:
[1 2 3] —>[1 3 2]
[3 2 1]—>[1 2 3]
[1 3 3]—->[3 1 3]
[1 1 5]—->[1 5 1]
2,解题思路
首先对数组从右边往左边进行扫描,找到第一个不是递增的元素,对该元素进行标记p。
然后从p元素开始,往右边进行一一扫描,找出比p大的最小元素,把该元素标记为q。
然后交换p和q元素。数组下标不变,但是数组里面的元素进行调换。
然后对p元素的右边所有的元素(不包括p元素)进行反转。即可以得到该数组的下一个更大的排列。
二,AC了的程序(java实现)
import java.util.*;
public class Test2{
public static void nextPermutation(int[] nums)
{
int len=nums.length;
int t1,p;
int q=0;
boolean flag=true;//flag用来查找数组从右边往左,不是递增的那个元素,如果找到了那个元素,则flag=false,如果没有找到,说明该数组已经达到了最大值
for(int i=len-1;i>0;i--)
{
if(nums[i-1]<nums[i]&&flag==true) //
{
p=nums[i-1]; //这一步,主要找到从右往左,不是递增的那个元素,标记该元素为p,其地址为i-1
for(int k=i;k<len;k++) //然后从p开始,往右边移动,找到比p大的最小元素,标记该元素的地址为q,注意q不等于该元素
{
if(nums[k]>p)
{
q = k;
}
}
t1=nums[i-1]; //用p元素与地址为q的元素进行交换。
nums[i-1]=nums[q];
nums[q]=t1;
int begin=i; //然后,把地址i-1的之后的元素进行反转。
int end=len-1;
while(begin<end)
{
int t2=nums[begin];
nums[begin]=nums[end];
nums[end]=t2;
begin++;
end--;
}
flag=false;
}
}
if(flag==true) //说明该元素的排列已经达到了最大值,因为把该数进行反转
{
int begin=0;
int end=len-1;
while(begin<end)
{
int t2=nums[begin];
nums[begin]=nums[end];
nums[end]=t2;
begin++;
end--;
}
}
}
public static void main(String []args)
{
Scanner scan=new Scanner(System.in);
int k=scan.nextInt(); //首先输入该数组的长度
int []nums;
nums=new int[k]; //
for(int i=0;i<k;i++) //输入数组的所有元素
{
nums[i]=scan.nextInt();
}
nextPermutation(nums);
for(int i=0;i<nums.length;i++)
{
System.out.print(nums[i]+" ");
}
System.out.println();
}
}