Leetcode刷题 - 排列组合类

78. 子集 - Subsets 

题目:https://leetcode.com/problems/subsets/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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. 初始化空集:[[]]
  2. 把第一个数加在之前初始化的集合中:[[],[1]]
  3. 把第二个数加在之前的集合中:[[], [1], [3], [1, 3]]
  4. 把第三个数加在之前的集合中:[[], [1], [3], [1,3],[5], [1, 5], [3, 5], [1,3,5]]

2. 组合

  • 最好是先sort原有数组
  • 初始化一个二维数组用来保存结果
  • 取原有数组里的值,一个一个的来处理
  • 循环结果数组的数,结合原有数组的值组合
  • 若原有数组有重复的值,需要检查重复性;将组合好的数组在之前的结果数组里寻找,若没找到则加到结果数组中;若找到了则忽略。

3. 排列(递归处理)

  • 初始化两个指针交换元素,j指向原有数组值,index指向 j 并在递归中依次加1
  • index指针向后移并递归交换
  • 再次交换元素为了变成原来的数组
  • 直到index指向数组的最后一个数,则将排列后的数组存入结果数组中

 参考资料:

  1. https://leetcode.com/problems/subsets/
  2. https://leetcode.com/problems/subsets-ii/
  3. https://leetcode.com/problems/permutations/
  4. https://leetcode.com/problems/letter-case-permutation/
  5. https://leetcode.com/problems/generate-parentheses/

__EOF__

本文作者cancantrbl
本文链接https://www.cnblogs.com/cancantrbl/p/13654493.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   cancantrbl  阅读(324)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示