leetcode 17 电话号码组合 笛卡尔积

一道关于笛卡尔积的面试题,原题为LeetCode 17。错误地使用回溯法会导致问题,因为回溯适合全排列而笛卡尔积有重复状态。最佳解决方案是使用迭代加队列。此外,提供了DFS解法的代码,以及使用Map初始化的便利性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述
此题是面试遇见的一道题,当时出的是笛卡尔积,和这个其实道理是一样的。
此题如果用标准的回溯做,是会出问题的。一开始做的时候,我是把他当全排列做的。

但全排列是没有重复状态的,每次选一个。一个状态的前继状态只有一种可能。但笛卡尔积问题是不止一个前继状态,有重复节点就很难记录,所以此题采用迭代+队列来做是最好的。

class Solution {
public:
    vector<string> letterCombinations(string digits) {
        int n = digits.size();
        vector<string> ans;
        if(n == 0)return ans;
        vector<string> v{"abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};

        queue<string> q;
        q.push("");

        for(auto d: digits)
        {
            int n = q.size();
            string cand = v[d-'2'];
            for(int i=0;i<n;i++)
            {
                string s = q.front(); q.pop();
                for(auto c: cand)
                {
                    q.push(s+c);
                }
            }
        }

        while(!q.empty())
        {
            ans.push_back(q.front());
            q.pop();
        }

        return ans;
    }
};

解法二:dfs
当时的我咋这么年轻呢,dfs都做这么久,直接上代码解决~ 此外,还有map的初始化方式,还是挺方便的。

class Solution {
map<int, string> m = {{2, "abc"}, {3, "def"}, {4, "ghi"}, {5, "jkl"}, 
    {6, "mno"}, {7, "pqrs"}, {8, "tuv"}, {9, "wxyz"}};
public:
    void dfs(vector<string>& ans, string tmp, string digits, int pos)
    {
        if(pos >= digits.size())
        {
            ans.push_back(tmp);
            return;
        }

        auto lst = m[digits[pos] - '0'];
        for(auto c: lst)
        {
            tmp += c;
            dfs(ans, tmp, digits, pos+1);
            tmp.pop_back();
        }
    }

    vector<string> letterCombinations(string digits) {
        vector<string> ans;
        if(digits.size() == 0)return ans;

        dfs(ans, "", digits, 0);

        return ans;
    }
};
### 关于关系代数的练习题和学习资料 #### 什么是关系代数? 关系代数是一种用于操作关系数据库的形式化语言,它由一组基于集合理论的操作符组成。这些操作符可以用来查询、更新以及管理关系型数据库中的数据[^2]。 #### 基本的关系代数操作 以下是关系代数的核心操作: - **并 (Union)**:两个关系的并集表示属于任一关系的所有元组。 - **差 (Difference)**:两个关系的差集表示只属于第一个关系而不属于第二个关系的所有元组。 - **投影 (Projection)**:从关系中选取某些列形成新的关系。 - **选择 (Selection)**:从关系中筛选满足特定条件的行。 - **笛卡尔积 (Cartesian Product)**:将两个关系组合成一个新的关系,其中包含所有可能的配对。 - **自然连接 (Natural Join)**:一种特殊的连接形式,通常要求两个关系具有至少一个共同属性[^3]。 #### 练习题示例 以下是一些常见的关系代数练习题目: 1. 设有两个关系 R(A, B) 和 S(B, C),写出它们的自然连接表达式。 解答:`R ⨝ S` 表示的是在公共属性 `B` 上进行匹配后的结果。 2. 如果有一个学生表 Student(SID, Name, Age) 和一门课程选修表 Course(CID, SID, Grade),如何找出选修 CID=‘C2’ 的学生的姓名? 方法一(先连接再选择): ```sql π_Name(σ_CID='C2'(Student × Course)) ``` 方法二(先选择后连接,更高效): ```sql π_Name(Student ⨝ σ_CID='C2'(Course)) ``` 3. 已知关系 T(X,Y,Z)={('a','b',1), ('c','d',2)} 和 U(Y,W)={('b','e'), ('f','g')},求其笛卡尔积的结果。 结果应为: ```plaintext X | Y | Z | W a | b | 1 | e c | d | 2 | g c | f | 2 | g ``` #### 学习资源推荐 为了更好地掌握关系代数的知识点,可以通过以下途径获取更多练习题及相关材料: - 参考书籍《数据库系统概论》,该书提供了丰富的习题供读者实践。 - 阅读文章如《数据库关系代数详解》及其后续的应用篇目[^1]。 - 使用在线平台完成互动式的编程挑战,例如 LeetCode 或 HackerRank 中涉及 SQL 查询的部分,间接锻炼了理解能力[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值