刷题漫漫路(一)|豆包MarsCode AI刷题

782 阅读6分钟

我最近尝试了掘金的AI刷题,还挺有意思的,旁边会有一个小助手来帮助自己刷题。我给大家分享一下我最近刷的几道题的解析,还有我对ai助手的使用心得。

好了废话不多说

首先是第一题——找单独的数

问题描述

在一个班级中,每位同学都拿到了一张卡片,上面有一个整数。有趣的是,除了一个数字之外,所有的数字都恰好出现了两次。现在需要你帮助班长小C快速找到那个拿了独特数字卡片的同学手上的数字是什么。

要求:

  1. 设计一个算法,使其时间复杂度为 O(n),其中 n 是班级的人数。
  2. 尽量减少额外空间的使用,以体现你的算法优化能力。

测试样例

样例1:

输入:cards = [1, 1, 2, 2, 3, 3, 4, 5, 5]
输出:4
解释:拿到数字 4 的同学是唯一一个没有配对的。

样例2:

输入:cards = [0, 1, 0, 1, 2]
输出:2
解释:数字 2 只出现一次,是独特的卡片。

样例3:

输入:cards = [7, 3, 3, 7, 10]
输出:10
解释:10 是班级中唯一一个不重复的数字卡片。

约束条件

  • 1 ≤ cards.length ≤ 1001
  • 0 ≤ cards[i] ≤ 1000
  • 班级人数为奇数
  • 除了一个数字卡片只出现一次外,其余每个数字卡片都恰好出现两次

讲解

第一种思路

这是一道相对简单的题目,我刚看到题目的时候就想到使用对象把每个数以 card: count 的形式存起来,然后再遍历这个对象找到count为1的数返回,我尝试了一下,可以解决,代码如下

function solution(cards) {
    const result = {};
    
    // 统计每个数字的出现次数
    for (let card of cards) {
        if (result[card] === undefined) {
            result[card] = 0;
        }
        result[card]++;
    }
    
    // 找到出现次数为1的数字
    for (let card in result) {
        if (result[card] === 1) {
            return card;
        }
    }
}

function main() {
    // Add your test cases here
    console.log(solution([1, 1, 2, 2, 3, 3, 4, 5, 5])); // 输出: 4
    console.log(solution([0, 1, 0, 1, 2])); // 输出: 2
}

main();

在刚开始的时候,我由于没有对result的值进行初始化,导致没能成功,这时我们就可以借助ai了。它可以帮我们直接检查编辑器的代码,并且给出相应的提示。

image.png

好了,问题是解决了,但是目前官方还不支持对js的提交,我又不会别的编程语言,该怎么办呢。别急,我们依旧来借助ai,让它帮助我们转换语言即可。

image.png 我通常会让它给我转成python代码,然后直接点击插入光标处。

image.png

第二种思路

提交后,我们还可以再想一想有没有更好的解决方法。一般可以从时间复杂度和空间复杂度来进行优化,很明显这题时间复杂度已经无法优化了,那看看空间复杂度。我们既然使用了对象,那看看能不能优化一下使用简单数据类型来解决。这时我灵光乍现,想到了可以使用异或。异或的规则是:对于任何整数 x,x ^ x = 0 且 x ^ 0 = x。如果我们对数组中的所有数字进行异或运算,最终的结果将是那个唯一的数字。

思路来了,最后写出来代码是这样的。

function solution(cards) {
    let result = 0;
    
    // 对数组中的所有数字进行异或运算
    for (let card of cards) {
        result ^= card;
    }
    
    return result;
}

function main() {
    // 添加你的测试用例
    console.log(solution([1, 1, 2, 2, 3, 3, 4, 5, 5])); // 输出: 4
    console.log(solution([0, 1, 0, 1, 2])); // 输出: 2
}

main();

第二题——最大矩形问题

问题描述

小S最近在分析一个数组 ℎ1,ℎ2,...,ℎ𝑁h1​,h2​,...,hN​,数组的每个元素代表某种高度。小S对这些高度感兴趣的是,当我们选取任意 𝑘k 个相邻元素时,如何计算它们所能形成的最大矩形面积。

对于 𝑘k 个相邻的元素,我们定义其矩形的最大面积为:

𝑅(𝑘)=𝑘×𝑚𝑖𝑛(ℎ[𝑖],ℎ[𝑖+1],...,ℎ[𝑖+𝑘−1])R(k)=k×min(h[i],h[i+1],...,h[i+k−1])

即,𝑅(𝑘)R(k) 的值为这 𝑘k 个相邻元素中的最小值乘以 𝑘k。现在,小S希望你能帮他找出对于任意 𝑘k,𝑅(𝑘)R(k) 的最大值。


测试样例

样例1:

输入:n = 5, array = [1, 2, 3, 4, 5]
输出:9

样例2:

输入:n = 6, array = [5, 4, 3, 2, 1, 6]
输出:9

样例3:

输入:n = 4, array = [4, 4, 4, 4]
输出:16

讲解

第一种思路

先分析题目:一个数组 array,其中包含 n 个元素,每个元素代表一个高度。你需要找到任意 k 个相邻元素所能形成的最大矩形面积。这个矩形的面积定义为这 k 个相邻元素中的最小值乘以 k。

我一看到这题就直接使用暴力遍历所有的k值和起始位置直接解出来了,代码如下。

function solution(n, array) {
    let max_area = 0;
    for (let k = 1; k <= n; k++) {
        for (let start = 0; start <= n - k; start++) {
            let height = Math.min(...array.slice(start, start + k));
            let area = k * height;
            max_area = Math.max(max_area, area);
        }
    }
    return max_area;
}

老样子,我们看看有没有可以优化的地方,既然是暴力解法,一般都可以优化的,再看一遍题目,最大矩形问题。等等……,最大,死去的记忆突然攻击我,我记得之前在做最值问题的时候一般都会使用到贪心算法或者是动态规划。容我想想,💡,想到了,可以通过单调栈来实现贪心,在每一步选择当前最优的矩形面积。

function solution(n, array) {
    let max_area = 0;
    let stack = [];

    for (let i = 0; i <= n; i++) {
        while (stack.length > 0 && (i === n || array[i] < array[stack[stack.length - 1]])) {
            let height = array[stack.pop()];
            let width = stack.length === 0 ? i : i - stack[stack.length - 1] - 1;
            max_area = Math.max(max_area, height * width);
        }
        stack.push(i);
    }

    return max_area;
}

// Add your test cases here
console.log(solution(5, [1, 2, 3, 4, 5]) === 9);
console.log(solution(6, [5, 4, 3, 2, 1, 6]) === 9);
console.log(solution(4, [4, 4, 4, 4]) === 16);

核心思路:

  1. 维护单调栈
  • 如果栈为空或者当前元素 h[i] 大于等于栈顶元素对应的高度,则将当前元素的索引 i 压入栈中。
  • 如果当前元素 h[i] 小于栈顶元素对应的高度,则说明栈顶元素作为最小值所能形成的矩形面积已经确定。此时,弹出栈顶元素,并计算以该元素为最小值的矩形面积。
  1. 计算矩形面积:
  • 对于每个弹出的栈顶元素 top,计算以 h[top] 为最小值的矩形面积。矩形的宽度为当前元素索引 i 减去新的栈顶元素索引 stack.peek() 再减去 1。
  1. 更新 max_area。
  • 处理剩余元素:遍历结束后,栈中可能还剩下一些元素。这些元素作为最小值所能形成的矩形面积也需要计算。

好了,这题到这里就结束了。讲完了刷题的思路,那来讲讲我对ai使用的心得吧

ai刷题心得

最近在体验了ai刷题后,我只能说有好有坏吧,其中有些测试样例是错误的,不过后面应该会改回来。 我认为不要太过于依赖ai了,要先自己多思考,建立好自己刷题的思维,到实在解决不了的问题再问ai。

我认为比较有用的就是这个右下角的ai fix,可以省去检查bug的时间。

image.png

还有就是检查编辑器的代码,可以很清晰的告诉你编辑器中出现的问题。

好了,这次分享就到这里了。