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
这题我看了半天都没搞懂啥是"下一个排列(next permutation)".找了些资料(http://www.geeksforgeeks.org/find-next-greater-number-set-digits/),才了解啥叫 next permutation.
这么弄:
假设 A = [2 1 8 7 6 5]
, 它的 next permutation 咋求? 这样求:
- 从右往左,5 6 7 8 都是增序,突然 1 降下来了, 那就所定 1;
- 1 右边有 8 7 6 5, 找比1大的但却是这四个数中较小的那个数, 就是 5 喽;
- 交换 1 和 5, 结果是
A = [2 5 8 7 6 1]
; - 然后 对
[8 7 6 1]
增序排序. 最后返回A = [2 5 1 6 7 8]
.
打完,收功!
这么做就能得到某序列的所谓的 next permutation 了?
是的!
为啥?
没为啥,遍个程序实现它就完事了!
题目要求中有个特殊情况,就是当 A = [4 3 2 1]
时,返回 A = [1 2 3 4]
.
以上就是本题的全部解释了.
更加详细的考虑及设置,在我的代码注释中写的很清楚.
人家想法,自个代码:
有个 cpp 副产品: reverse(A.begin() + start, A.end());
这个 start 是 A = [2 1 8 7 6 5]
中元素 8 的 index, start = 2.
(O(n)) time, (O(1)) extra space.
严格来说,里面用到了排序,就不是(O(n)) time 了.
// e.g.
// A = [2 1 8 7 6 5]
// step 1: from right to left, seek element '1';
// step 2: from right to left, seek '5' and swap(A[1], A[5])
// --- After step 2, A = [2 1 8 7 6 5] --> A = [2 5 8 7 6 1]
// step 3: reverse(A.begin() + 2, A.end())
// --- return A = [2 5 1 6 7 8]
// special case: A = [4 3 2 1] --> will return A = [1 2 3 4]
void nextPermutation(vector<int>& A) {
const int n = A.size();
if (n == 0 || n == 1)
return; //special case
int start;
// 4 3 2 1, can not found A[i]<A[i+1]
bool found = false;
// step 1
for (int i = n - 2; i >= 0; i--) {
if (A[i] < A[i + 1]) {
start = i + 1;
found = true; // found the case A[i]<A[i+1]
break;
}
}
// special case
// 4 3 2 1 --> return 1 2 3 4 directly
if (found == false) {
reverse(A.begin(), A.end());
return;
}
// step 2
for (int j = n - 1; j >= start; j--) {
if (A[j] > A[start - 1]) {
swap(A[j], A[start - 1]);
break;
}
}
// step 3
reverse(A.begin() + start, A.end());
return;
}