刷题实践 | 豆包MarsCode AI 刷题

59 阅读6分钟

问题描述

小S正在帮助她的朋友们建立一个搜索引擎。为了让用户能够更快地找到他们感兴趣的帖子,小S决定使用倒排索引。倒排索引的工作原理是:每个单词都会关联一个帖子ID的列表,这些帖子包含该单词,且ID按从小到大的顺序排列。
例如,单词“夏天”可能出现在帖子1、帖子3和帖子7中,那么这个单词的倒排链就是 [1, 3, 7]。如果用户想同时找到包含“夏天”和“海滩”的帖子,小S需要找出两个倒排链的交集,且将结果按照从大到小的顺序输出。现在,给定两个单词的倒排链数组 a 和 b,请你帮助小S找出同时包含这两个单词的帖子ID,并按从大到小的顺序返回结果。

解法一:
`#include #include #include <unordered_set> #include

using namespace std;

vector solution(vector &a, vector &b) { vector result; unordered_set hashSet;

// 将数组 a 的元素存入哈希表 for (int num : a) { hashSet.insert(num); }

// 遍历数组 b,检查元素是否存在于哈希表中 for (int num : b) { if (hashSet.find(num) != hashSet.end()) { result.push_back(num); // 为了避免重复添加相同的元素,从哈希表中删除该元素 hashSet.erase(num); } }

// 反转结果数组,使其按从大到小的顺序排列 sort(result.rbegin(), result.rend());

return result; }

int main() { vector a1 = {1, 2, 3, 7}; vector b1 = {2, 5, 7}; vector res1 = solution(a1, b1); cout << (res1 == vector{7, 2}) << endl;

vector a2 = {1, 4, 8, 10}; vector b2 = {2, 4, 8, 10}; vector res2 = solution(a2, b2); cout << (res2 == vector{10, 8, 4}) << endl;

vector a3 = {3, 5, 9}; vector b3 = {1, 4, 6}; vector res3 = solution(a3, b3); cout << (res3 == vector{}) << endl;

vector a4 = {1, 2, 3}; vector b4 = {1, 2, 3}; vector res4 = solution(a4, b4); cout << (res4 == vector{3, 2, 1}) << endl;

return 0; }`

方法二:
`#include #include #include // for std::reverse using namespace std;

vector solution(vector& a, vector& b) { vector result; int i = 0, j = 0;

// 遍历数组 ab
while (i < a.size() && j < b.size()) {
    if (a[i] == b[j]) {
        // 找到交集元素,加入结果数组
        result.push_back(a[i]);
        i++;
        j++;
    } else if (a[i] < b[j]) {
        // a 中的元素较小,移动 a 的指针
        i++;
    } else {
        // b 中的元素较小,移动 b 的指针
        j++;
    }
}

// 反转结果数组,使其按从大到小的顺序排列
reverse(result.begin(), result.end());

return result;

}

int main() { vector a1 = {1, 2, 3, 7}; vector b1 = {2, 5, 7}; vector res1 = solution(a1, b1); cout << (res1 == vector{7, 2}) << endl;

vector<int> a2 = {1, 4, 8, 10};
vector<int> b2 = {2, 4, 8, 10};
vector<int> res2 = solution(a2, b2);
cout << (res2 == vector<int>{10, 8, 4}) << endl;

vector<int> a3 = {3, 5, 9};
vector<int> b3 = {1, 4, 6};
vector<int> res3 = solution(a3, b3);
cout << (res3 == vector<int>{}) << endl;

vector<int> a4 = {1, 2, 3};
vector<int> b4 = {1, 2, 3};
vector<int> res4 = solution(a4, b4);
cout << (res4 == vector<int>{3, 2, 1}) << endl;

return 0;}  

知识点

  1. 哈希表 (unordered_set)

    • unordered_set 是一个无序集合,支持平均常数时间复杂度的插入和查找操作。
    • 使用 insert 方法将元素插入哈希表。
    • 使用 find 方法查找元素,如果找到则返回指向该元素的迭代器,否则返回 end()
    • 使用 erase 方法删除元素,避免重复添加相同的元素。
  2. 逆向排序

    • 使用 sort(result.rbegin(), result.rend()) 将结果数组按从大到小的顺序排序。
  3. 迭代器

    • rbegin() 和 rend() 分别返回逆向迭代器,指向容器的最后一个元素和第一个元素之前的位置
    • 比较

  4. 时间复杂度

    • 方法一:时间复杂度为 O(n+m)O(n+m),其中 nn 和 mm 分别是数组 a 和 b 的长度。这是因为插入和查找哈希表的操作都是平均常数时间复杂度。
    • 方法二:时间复杂度为 O(n+m)O(n+m),其中 nn 和 mm 分别是数组 a 和 b 的长度。这是因为每个元素最多只会被访问一次。
  5. 空间复杂度

    • 方法一:空间复杂度为 O(n)O(n),因为需要额外的空间来存储哈希表。
    • 方法二:空间复杂度为 O(1)O(1),因为只使用了常数级别的额外空间。
  6. 适用场景

    • 方法一:适用于数组较大且需要快速查找的情况。
    • 方法二:适用于数组已经排序且不需要额外空间的情况。

结论

  • 方法一 使用哈希表,适合处理较大的数据集,查找速度快,但需要额外的空间。
  • 方法二 使用双指针法,适合处理已经排序的数组,不需要额外空间,但查找速度稍慢。

ai练习

1. 理论学习

利用AI进行理论学习

  • 课程推荐:使用AI工具推荐适合你的算法课程。例如,你可以输入你的背景和目标,AI会为你推荐合适的在线课程或书籍。
  • 概念解释:当你遇到不懂的概念或算法时,可以使用AI工具获取详细的解释和示例。例如,你可以询问“什么是动态规划?”或“如何实现二分查找?”。
  • 视频教程:AI可以推荐相关的视频教程,帮助你通过视觉和听觉的方式更好地理解复杂的算法概念。

2. 实践练习

利用AI进行实践练习

  • 题库推荐:使用AI工具推荐适合你当前水平的算法题目。例如,你可以输入你的技能水平,AI会为你推荐适合的LeetCode题目。
  • 代码生成:当你卡在一个问题上时,可以使用AI生成初步的代码框架,帮助你快速上手。例如,你可以询问“生成一个二分查找的代码框架”。
  • 代码调试:使用AI工具帮助你调试代码。例如,你可以输入你的代码和错误信息,AI会给出可能的解决方案。

3. 反馈循环

利用AI进行反馈和评估

  • 代码审查:使用AI工具对你的代码进行审查,指出潜在的问题和优化建议。例如,你可以上传你的代码,AI会给出详细的代码审查报告。
  • 性能评估:使用AI工具评估你的算法性能,帮助你了解时间和空间复杂度。例如,你可以询问“我的算法的时间复杂度是多少?”。
  • 错误分析:当你提交的代码未能通过某些测试用例时,使用AI工具帮助你分析错误原因。例如,你可以上传失败的测试用例,AI会给出可能的原因和解决方案。

4. 持续改进

利用AI进行持续改进

  • 学习路径规划:使用AI工具规划你的学习路径,根据你的进度和目标推荐下一步的学习内容。例如,你可以输入你的长期目标,AI会为你制定一个详细的学习计划。
  • 定期评估:使用AI工具定期评估你的进步,帮助你识别弱点并进行针对性的训练。例如,你可以设置每周一次的评估,AI会生成你的进步报告并提出改进建议。
  • 社区互动:利用AI工具连接到算法学习社区,与其他学习者交流经验和问题。例如,你可以加入AI推荐的算法学习群组,参与讨论和互助。