排列 / 组合 / 子集合
1.数组中元素的全排列
题目链接:https://www.acwing.com/problem/content/96/ (算法竞赛进阶指南)
https://www.lintcode.com/problem/permutations-ii/description/ (Lintcode)
思路:
1.对数组进行排序
2.枚举每一个位置上选择什么数字
3.跳过重复的元素
代码:
class Solution { public: vector<int> nums; vector<vector<int>> res; vector<int> temp; int n; vector<bool> st; void calc(int k) { if(k == n + 1) { res.push_back(temp); return; } for(int i = 0; i < n; i++) { if(st[i] == true) continue; st[i] = true; temp.push_back(nums[i]); calc(k + 1); st[i] = false; temp.pop_back(); while(i + 1 < n && nums[i + 1] == nums[i]) i++; } } vector<vector<int>> permuteUnique(vector<int> &s) { n = s.size(); nums = s; sort(nums.begin(), nums.end()); st = vector<bool>(n, false); calc(1); return res; } };
2.数组中元素的组合
题目链接:https://www.acwing.com/problem/content/description/95/ (算法竞赛进阶指南)
思路:枚举每个数字选择或者不选择, 二进制存储选择了哪些数字
代码:
#include <bits/stdc++.h> using namespace std; int n, m; void dfs(int u, int sum, int state) { if(sum + n - u < m) return; if(sum == m) { for(int i = 0; i < n; i++) if(state >> i & 1) cout << i + 1 << " "; cout << endl; return; } if(u == n) return; dfs(u + 1, sum + 1, state + (1 << u)); dfs(u + 1, sum, state); } int main() { cin >> n >> m; //第几个数, 选了几个数,选了什么数字 dfs(0, 0, 0); return 0; }
3.集合的子集
题目链接:https://www.acwing.com/problem/content/94/ (算法竞赛进阶指南)
https://www.lintcode.com/problem/subsets-ii/description (LintCode)
思路:枚举每个数字选或者不选,直到最后一个位置。遇到连续的相同元素跳过
代码:
class Solution { public: /** * @param nums: A set of numbers. * @return: A list of lists. All valid subsets. */ vector<vector<int> > res; vector<int> nums; vector<int> temp; int n; void dfs(int a, int b) { if(a == n) { for(int i = 0; i < n; i++) { if(b >> i & 1) { temp.push_back(nums[i]); } } res.push_back(temp); temp.clear(); return; } dfs(a + 1, b + (1 << a)); while(a + 1 < n && nums[a] == nums[a + 1]) a++; dfs(a + 1, b); } vector<vector<int>> subsetsWithDup(vector<int> &s) { // write your code here n = s.size(); nums = s; sort(nums.begin(), nums.end()); dfs(0, 0); return res; } };
4.上升子序列
题目链接:https://leetcode.com/problems/increasing-subsequences/ (Leetcode)
思路:不能打乱原数组的顺序,因此不能通过排序进行去重。
1.二进制枚举每一种选择的可能,将不符合要求的方案直接删除
2.利用set进行去重
代码:
class Solution { public: vector<vector<int>> findSubsequences(vector<int>& nums) { int size = nums.size(); set<vector<int>> f; vector<vector<int> > res; for(int i = 0; i < (1 << size); i++) { vector<int> temp; for(int j = 0; j < size; j++) { if(i & (1 << j)) { temp.push_back(nums[j]); } } for(int j = 1; j < temp.size(); j++) { if(temp[j] < temp[j - 1]) { temp.clear(); break; } } if(temp.size() >= 2) if(f.find(temp) == f.end()) { f.insert(temp); res.push_back(temp); } } return res; } };

浙公网安备 33010602011771号