LeetCode解题 31:Next Permutation
Problem 31: Next Permutation [Medium]
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 and use only constant 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
来源:LeetCode
解题思路
下一个更大的排列应该从改变数值后影响最小的位数考虑。
- 第一层循环中,设置指针
i
从后往前考察,是否有某一位上的数nums[i]
,其值可以通过与一个更小位上的数 K K K( K ∈ K\in K∈nums[i+1]
~nums[n-1]
)做交换而变大,并且变大的程度最小,这要求:
K = min ( { n u m s [ j ] ∣ n u m s [ j ] > n u m s [ i ] , j ∈ [ i + 1 , n − 1 ] } ) K = \min(\{nums[j]\mid nums[j]>nums[i],j\in[i+1,n-1]\}) K=min({nums[j]∣nums[j]>nums[i],j∈[i+1,n−1]}) - 第二层循环中,由于之前没有找到可以改变数值的位,说明指针
i
后的数按降序排列,则当从后往前寻找比nums[i]
大的数值时,但凡存在这样的数nums[j]
,都一定是nums[i+1]
~nums[n-1]
中符合要求的最小数值。 - 找到可以交换的数
nums[j]
后,与nums[i]
做交换,此时的nums[i+1]
~nums[n-1]
仍然保持降序排列,只要使用双指针将其改为升序排列,即是符合题意的下一个更大排列。 - 此外,当排列已经是降序排列时,同样只需用双指针法改为升序排列即可。
两层循环时间复杂度为O(n2),双指针法排序时间复杂度O(n),因此总时间复杂度O(n2)。
要点:双指针
Solution (Java)
class Solution {
public void nextPermutation(int[] nums) {
int N = nums.length;
int temp, l, r;
for(int i = N-2; i >= 0; i--){
for(int j = N-1; j > i; j--){
if(nums[j] > nums[i]){
temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
//sort nums[i+1]~nums[N-1](descending order) in ascending order
l = i+1;
r = N-1;
while(l < r){
temp = nums[l];
nums[l] = nums[r];
nums[r] = temp;
l++;
r--;
}
return;
}
}
}
l = 0;
r = N-1;
while(l < r){
temp = nums[l];
nums[l] = nums[r];
nums[r] = temp;
l++;
r--;
}
}
}
修改过程
- 一开始的思路是使用指针
i
从后往前检查,在i
之前是否有比nums[i]
小的数值nums[j]
,小就替换,然后将j
之后的数从小到大排序。若输入[4,2,0,2,3,2,0],则这种思路输出[4,2,2,0,0,2,3],正确答案应该是[4,2,0,3,0,2,2]。