Leetcode刷题 - 排列组合类
78. 子集 - Subsets
题目:https://leetcode.com/problems/subsets/
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> output;
output.push_back({});
for (int i = 0; i < nums.size(); i++){
int size = output.size();
for (int j = 0; j < size; j++){
auto sub = output[j];
sub.push_back(nums[i]);
output.push_back(sub);
}
}
return output;
}
};
90. 子集 - Subsets II
题目:https://leetcode.com/problems/subsets-ii/
class Solution {
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<vector<int>> output;
output.push_back({});
for (int i = 0; i < nums.size(); i++){
int size = output.size();
for (int j = 0; j < size; j++){
auto temp = output[j];
temp.push_back(nums[i]);
// handle duplicate cases
bool found = false;
// find whether there is a duplicate case
for (int k = 0; k < output.size(); k ++){
if (temp == output[k]){
found = true;
break;
}
}
if(!found)
output.push_back(temp);
}
}
return output;
}
};
46. 排列 - Permutation
题目:https://leetcode.com/problems/permutations/
class Solution {
public:
vector<vector<int>> permute(vector<int>& nums) {
vector<vector<int>> result;
helper(nums, 0, result);
return result;
}
void helper (vector<int>& nums, int index, vector<vector<int>>& ans){
// 如果 i 移到数组的最后,则加入排过的数组并加入结果数组中
if (index == nums.size()){
ans.push_back(nums);
return;
}
// 两个指针,index作为递归处理, j作为迭代处理
for (int j = index; j < nums.size(); j ++){
//内部交换
swap(nums[index], nums[j]);
//递归处理
helper(nums, index+1, ans);
//变回原来的数组
swap(nums[index], nums[j]);
}
}
};
剑指OFFER:字符串排列组合
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则按字典序打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
题目:https://www.nowcoder.com/practice/fe6b651b66ae47d7acce78ffdd9a96c7?tpId=13&&tqId=11180&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking
class Solution {
public:
vector<string> Permutation(string str) {
vector<string> result;
if(str.size() == 0) return result;
helper(str, 0, result);
// 整理排序顺序
sort(result.begin(), result.end());
return result;
}
void helper(string str, int index, vector<string> & ans){
//若组合到最后一个,则弹出
if (index == str.size()){
ans.push_back(str);
return;
}
for (int j = index; j < str.size(); j++){
// 处理重复元素
if(j!=index && str[j] == str[index])
continue;
// 交换
swap(str[index], str[j]);
helper(str, index+1, ans);
// 交换回来
swap(str[index], str[j]);
}
}
};
784. 字母大小写排列 - Letter Case Permutation
class Solution {
public:
vector<string> letterCasePermutation(string S) {
vector<string> res({S}); // 将S加入结果数组中
// 取原有数组的值
for(int i = 0; i < S.size(); i ++){
if (isdigit(S[i])) continue;
int size = res.size();
// 迭代结果数组
for (int j = 0; j < size; j++){
string temp = res[j];
temp[i] ^= 32; //利用XOR with 32 changes改变大小写
/*****
* 详解XOR
* 大小写字母的二进制ASCII码只有第6位有所不同
* 利用异或位运算(XOR)来实现相互转换。
* 32 or(1 << 5)
* 或者 temp[i] ^= ' '; 因为空格的ASCII为32
******/
res.push_back(temp);
}
}
return res;
}
};
22. 括号生成排列 - Generate Parentheses
class Solution {
public:
vector<string> ans;
vector<string> generateParenthesis(int n) {
//利用递归方法
helper("", n, n);
return ans;
}
void helper(string s, int open, int close){
if (open == 0 && close == 0){
ans.push_back(s);
return;
}
if (open > 0) helper(s+"(", open - 1, close);
// “(” 必须在 “)”之前,所以没加 “)”之前,"(" 要比 “)”多
if(open < close) helper(s+")", open, close - 1);
}
};
总结
1. 子集模式的举例:[1, 3, 5]
- 初始化空集:[[]]
- 把第一个数加在之前初始化的集合中:[[],[1]]
- 把第二个数加在之前的集合中:[[], [1], [3], [1, 3]]
- 把第三个数加在之前的集合中:[[], [1], [3], [1,3],[5], [1, 5], [3, 5], [1,3,5]]
2. 组合
- 最好是先sort原有数组
- 初始化一个二维数组用来保存结果
- 取原有数组里的值,一个一个的来处理
- 循环结果数组的数,结合原有数组的值组合
- 若原有数组有重复的值,需要检查重复性;将组合好的数组在之前的结果数组里寻找,若没找到则加到结果数组中;若找到了则忽略。
3. 排列(递归处理)
- 初始化两个指针交换元素,j指向原有数组值,index指向 j 并在递归中依次加1
- index指针向后移并递归交换
- 再次交换元素为了变成原来的数组
- 直到index指向数组的最后一个数,则将排列后的数组存入结果数组中
参考资料:
- https://leetcode.com/problems/subsets/
- https://leetcode.com/problems/subsets-ii/
- https://leetcode.com/problems/permutations/
- https://leetcode.com/problems/letter-case-permutation/
- https://leetcode.com/problems/generate-parentheses/

浙公网安备 33010602011771号