1. Next Permutation
首先,从最尾端开始往前寻找两个相邻元素,令第一元素为 *i,第二元素为 *ii,且满足 *i < *ii;找到这样一组相邻元素后,再从尾端开始往前检验,找出第一个大于 *i 的元素,令为 *j,将 i,j 元素对调,再将 ii 之后的所有元素颠倒排列。
1 void nextPermutation(vector<int>& nums) { 2 if(nums.empty()) 3 return; 4 int n = nums.size(); 5 for (int i = n - 2; i >=0; --i) { 6 if (nums[i] >= nums[i + 1]) 7 continue; 8 int j = n - 1; 9 while (j >= 0 && nums[j] <= nums[i]) --j; 10 swap(nums[i], nums[j]); 11 reverse(nums.begin() + i + 1, nums.end()); 12 return; 13 } 14 // 进行至最前面,重排 15 reverse(nums.begin(), nums.end()); 16 }
2.Prev Permutation
首先,从最尾端开始往前寻找两个相邻元素,令第一元素为 *i,第二元素为 *ii,且满足 *i > *ii;找到这样一组相邻元素后,再从尾端开始往前检验,找出第一个小于*i 的元素,令为 *j,将 i,j 元素对调,再将 ii 之后的所有元素颠倒排列。
1 void prevPermutation(vector<int>& nums) { 2 if(nums.empty()) 3 return; 4 int n = nums.size(); 5 for (int i = n - 2; i >=0; --i) { 6 if (nums[i] <= nums[i + 1]) 7 continue; 8 int j = n - 1; 9 while (j >= 0 && nums[j] >= nums[i]) --j; 10 swap(nums[i], nums[j]); 11 reverse(nums.begin() + i + 1, nums.end()); 12 return; 13 } 14 reverse(nums.begin(), nums.end()); 15 }
3. Permutations(全排列)
(1)回溯法
1 vector<vector<int>> permute(vector<int>& nums) { 2 vector<vector<int>> res; 3 vector<int> cur; 4 vector<bool> visited(nums.size(), false); 5 6 dfs(nums, res, cur, visited); 7 8 return res; 9 } 10 11 void dfs(const vector<int>& nums, vector<vector<int>>& res, vector<int>& cur, vector<bool>& visited) { 12 if (cur.size() == nums.size()) { 13 res.push_back(cur); 14 return; 15 } 16 17 for (int i = 0; i < nums.size(); ++i) { 18 if (visited[i] == false) { 19 cur.push_back(nums[i]); 20 visited[i] = true; 21 dfs(nums, res, cur, visited); 22 cur.pop_back(); 23 visited[i] = false; 24 } 25 } 26 }
(2)递归 1:
1 vector<vector<int>> permute(vector<int>& nums) { 2 vector<vector<int>> res; 3 4 recursive(nums, res, 0); 5 6 return res; 7 } 8 9 void recursive(vector<int>& nums, vector<vector<int>>& res, int start) { 10 if (start >= nums.size()) { 11 res.push_back(nums); 12 } 13 for (int i = start; i < nums.size(); ++i) { 14 swap(nums[start], nums[i]); 15 recursive(nums, res, start + 1); 16 swap(nums[start], nums[i]); 17 } 18 }
递归2:
当n=1时,数组中只有一个数a1,其全排列只有一种,即为a1
当n=2时,数组中此时有a1a2,其全排列有两种,a1a2和a2a1,那么此时我们考虑和上面那种情况的关系,我们发现,其实就是在a1的前后两个位置分别加入了a2
当n=3时,数组中有a1a2a3,此时全排列有六种,分别为a1a2a3, a1a3a2, a2a1a3, a2a3a1, a3a1a2, 和 a3a2a1。那么根据上面的结论,实际上是在a1a2和a2a1的基础上在不同的位置上加入a3而得到的。
(3)借用next_permutation的函数
4. The Kth Permutation Sequence
The set [1,2,3,…,n]
contains a total of n! unique permutations. Given n and k, return the kth permutation sequence.
1 string getPermutation(int n, int k) { 2 string res; 3 string dict = "123456789"; 4 int factorial = 1; 5 for (int i = 1; i < n; ++i) { 6 factorial *= i; 7 } 8 --k; 9 while (n--) { 10 int pos = k / factorial; 11 res += dict[pos]; 12 k %= factorial; 13 factorial /= (n ? n : 1); 14 dict.erase(pos, 1); 15 } 16 return res; 17 }