Permutation (LeetCode)
Question:
https://leetcode.com/problems/permutations-ii/
解答:
需要考虑有值重复的情况,跟Permutations I一样的解法,只是需要考虑如何去除重复的 情况。
两种解法:
1. recursive:
这种情况不需要排序。
P(N) = P(1)+P(N-1),就是说当前N个结点的Permutation是第一个结点和后面N-1个结点的Permutation的组合。第一个结点的取值可以是数组的任何一个。所以依次交换,剩下的N-1点同法递归求Permutation.
重复的情况,如果当前点值是K,则后面遇到点值为K的时候需要略过,因为两者交换没有区别。同时如果后面点值是Q,但是Q以前已经跟K交换过了,这时也需要略过。
2. Iterative:
需要事先把数组排好序。
从后面往前找到第一个数是小于后面的数的,设为i,然后重新从后面开始找第一个大于num[i]的数,设为j,因为(i, i+1)是(i,n-1)唯一一组递增的数,所以(i+1, n-1)都是递减的。i,j交换,然后反转(i+1, n-1),这样数组就是正序的。
这样的做的道理是,比如当前数组是:
1 2 3 4 5,后面4位处理到最后会变成1 5 4 3 2,这时我们需要1和2交换,相当于重新开始处理后4位,所以需要重置后4位,这样才能重新开始计算。
class Solution { public: vector<vector<int> > permuteUnique(vector<int> &num) { vector<vector<int>> result; std::sort(num.begin(), num.end()); permuteIterate(num, result); //permute(num, result, 0); return result; } void permuteIterate(vector<int>& num, vector<vector<int>>& result) { std::sort(num.begin(), num.end()); int n = num.size(); while (1) { result.push_back(num); int i = n-2; while (i >= 0) { // find last pair that num[i] > num[i-1] if (num[i+1] > num[i]) break; i--; } if (i < 0) break; // swap num[i] with least great number int j = n-1; for (; j > i; j--) { if (num[j] > num[i]) break; } // swap num[i] and num[j] swap(num, i, j); // reverse from num[i+1] to num[n-1] int pl = i+1; int pr = n-1; while (pl < pr) { swap(num, pl, pr); pl ++; pr --; } } } void permute(vector<int>& num, vector<vector<int>>& result, int index) { if (index == num.size()-1) { result.push_back(num); return; } set<int> visited; for (int i = index; i < num.size(); i++) { if (visited.find(num[i]) != visited.end()) continue; visited.insert(num[i]); swap(num, index, i); permute(num, result, index+1); swap(num, index, i); } } void swap(vector<int>& num, int i, int j) { if (i == j) return; int temp = num[i]; num[i] = num[j]; num[j] = temp; } };
浙公网安备 33010602011771号