下一个字典序的产生思想
当前字典序和下一个字典序一定是共同前缀的
从最后一位往前递归,保证后缀子串是从小到大有序的
(1) 比较当前nums[cur]和后缀子串,如果后缀子串中存在比当前nums[cur]大的数,则该nums[cur]与后缀子串组成的新的后缀子串存在更大的字典序,只需要找到原子串中比nums[cur]第一个大的元素,并与nums[cur]交换,即是下一个字典序.则完成任务,一路返回即可.
(2)如果不存在比当前nums[cur]大的数,则表明从最后一位到cur的位置都是最大字典序,则把该数插入到最后位置,保证后缀子串有序.
为什么要维护后缀子串为有序递增?是为了保证新后缀为最小字典序.这样当有可交换的cur时,直接交换cur和可交换的数即为下一个字典序.
如
“1,4,2,3,1”
(1) '1' ,后缀没有子串,返回上一层
(2) '3',后缀'1', 3>1 , 无下一个字典序, 插入3 后缀子串"1,3"
(3)'2',后缀'1,3', 2>1,2<3,交换2,3 => 1,4,3,1,2 . 找到下一个字典序,一路返回.
class Solution {
public void nextPermutation(int[] nums) {
if(nums.length<=1) return;
permutation(nums,0,nums.length-1);
}
private boolean permutation(int[] nums, int s, int e){
if (e-s<=0) return false;
boolean flag = permutation(nums,s+1, e);
if(flag) return flag;
for(int i=s+1;i<=e;i++)
{
if(nums[i]>nums[s]){
swap(nums, i, s);
return true;
}
}
for(int i=s;i<e;i++){
if(nums[i]>nums[i+1]){
swap(nums,i,i+1);
}
}
return flag;
}
private void swap(int[] nums, int i, int j){
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
时间复杂度O(n),空间复杂度O(n) 运行时间超过100%,运行空间超过78%