下一个组合数。因为有数组内一部分的排序,c++更自然些。算法很简单,从末尾向开头找不合顺序的,然后调换,然后把后面的排序。调换要找到那个刚好比pivot大的元素,因为再小的,如果换过去,这些顺序已经排过了。
#include <vector> #include <algorithm> using namespace std; class Solution { public: void nextPermutation(vector<int> &num) { // Start typing your C/C++ solution below // DO NOT write int main() function int idx = num.size() - 1; bool inorder = true; while ( idx > 0) { if ((num[idx] > num[idx-1])) { inorder = false; break; } idx--; } if (inorder) { sort(num.begin(), num.end()); return; } idx--; // idx is the number need to be exchanged int minIdx = INT_MAX; for (int i = idx+1; i < num.size(); i++) { if (num[i] > num[idx]) { if (minIdx == INT_MAX || num[i] < num[minIdx]) { minIdx = i; } } } swap(num, idx, minIdx); sort(num.begin() + idx + 1, num.end()); } void swap(vector<int> &num, int a, int b) { int tmp = num[a]; num[a] = num[b]; num[b] = tmp; } };
第二遍:之前的方法里面用了sort,其实不算是O(n)的。C++库里面的方法是用reverse,原因是swap之后,后半部分其实正好倒序,这样reverse就相当于sort了。如果用sort,Annie的写法更简洁。https://github.com/AnnieKim/LeetCode/blob/master/NextPermutation.h
class Solution { public: void nextPermutation(vector<int> &num) { int i = num.size() - 1; while (i > 0 && num[i] <= num[i-1]) i--; if (i == 0) { reverse(num, 0, num.size()-1); return; } int pivot = num[i-1]; int idx = -1; for (int j = num.size()-1; j >= i; j--) { if (idx == -1 && num[j] > pivot) { idx = j; } else if (idx != -1 && num[j] > pivot && num[j] < num[idx]) { idx = j; } } swap(num, i-1, idx); reverse(num, i, num.size()-1); } void reverse(vector<int> &num, int l, int r) { while (l < r) { swap(num, l, r); l++; r--; } } void swap(vector<int> &num, int i, int j) { int tmp = num[i]; num[i] = num[j]; num[j] = tmp; } };