问题链接:http://oj.leetcode.com/problems/next-permutation/
问题描述: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
问题API:public void nextPermutation(int[] num)
问题分析:这本是一个数学题,具体规律会在permutation sequence那题有的看到。下面简要说一下步骤:
Step 1. 从后往前找到一个第一个非递增的元素p,如果p不存在,翻转整个list便是要的结果(因为实际上这已经是最后一个Permutation,翻转整个list就是第一个permutation)
Step 2. 从p开始找到第一个小于等于P的数字t,然后交换p和t – 1, 然后翻转p之后的元素,就是结果。如果找不到就交换p和最后一个元素,再翻转p之后的元素。
代码如下:
public void nextPermutation(int[] num) {
if(num == null || num.length <= 1)
return;
int first = -1;
for(int i = num.length - 2; i >= 0; i--){
if(num[i] < num[i + 1]){//step 1.
first = i;
break;
}
}
if(first != -1){
boolean isSwitch = false;
for(int i = first + 1; i < num.length; i++){
if(num[i] <= num[first]){//step 2.
num[i - 1] ^= num[first];
num[first] ^= num[i - 1];
num[i - 1] ^= num[first];
isSwitch = true;
break;
}
}
if(!isSwitch){
num[num.length - 1] ^= num[first];
num[first] ^= num[num.length - 1];
num[num.length - 1] ^= num[first];
}
}
reverse(num, first + 1, num.length - 1);
}
public void reverse(int[] num, int h, int t){
while(h < t){
num[h] = num[h] ^ num[t];
num[t] = num[h] ^ num[t];
num[h] = num[h] ^ num[t];
h++;
t--;
}
}更新一下代码让代码更加简洁和易懂:
public void nextPermutation(int[] num) {
int p = -1;
for(int i = num.length - 2; i >= 0; i--){
if(num[i] < num[i + 1]){//第一步,找到第一个非递增元素,或者p就等于-1了
//p = -1意味着找不到,可以直接翻转整个数组
p = i;
break;
}
}
int t = num.length - 1;
for(int i = p + 1; i <= num.length; i++){
if(p != -1 && (i == num.length || num[p] >= num[i])){
//第二步,找到第一个小于等于num[p]的num[t].然后交换p和t - 1的位置的数。又或者在前一个数字找不到的前提下交换p和num[t - 1]。
//前提是找到了p的位置,也就是p不等于-1
t = i - 1;
int tmp = num[p];
num[p] = num[t];
num[t] = tmp;
break;
}
}//第三步,翻转p之后的所有数字。p = -1的情况实际就是翻转全数组。
reverse(num, p + 1, num.length - 1);
}
public void reverse(int[] num, int head, int tail){
while(head < tail){
int tmp = num[head];
num[head] = num[tail];
num[tail] = tmp;
head++;
tail--;
}
}
本文介绍如何实现将一组数字重新排列为字典序中下一个更大的排列。若无法排列,则将其变为最小的排列(升序)。通过两步操作实现:寻找非递增元素并交换,随后翻转部分数组。
542

被折叠的 条评论
为什么被折叠?



