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

539 阅读5分钟

这期继续带来的是豆包的ai刷题,继上次刷题分享,这次我们来挑战一下困难题

废话不多说,

先来一道中等题当开胃菜

第一题——数字的奥秘:AI与‘11’

问题描述 小U最近开发了一个独特的AI模型,它有一个有趣的特点:当你给出一系列数字时,例如从1到N,AI会将这些数字视为一个没有空格或逗号的连续字符串。例如,当你给定N=11时,AI会展示的内容是“1234567891011”。小U对数字“11”非常感兴趣,她想知道在这个连续字符串中,子字符串“11”出现的次数是多少。

你需要帮助小U编写一个程序,给定一个整数N,计算子字符串“11”在AI模型感知的序列中出现的次数。

测试样例 样例1

输入:N = 11 输出:1

样例2

输入:N = 100 输出:2

样例3

输入:N = 111 输出:6

解答

老实说,最近在公司实现的几个需求都是使用正则表达式来写的,所以我一看到这题我就想到了用正则表达式秒了,直接用正则表达式找出11的数组,返回长度就行了。

所以一开始我的代码是这样的

function solution(N) {
    let str = '';
    for (let i = 1; i <= N; i++) {
        str += i;
    }
    // 使用正则表达式匹配非重叠的子字符串“11”
    const matches = str.match(/11/g);
    // 处理匹配结果,返回匹配的次数
    return matches ? matches.length : 0;
}

function main() {
    console.log(solution(11) === 1); // 输出: true
    console.log(solution(100) === 2); // 输出: true
    console.log(solution(111) === 6); // 输出: true
}

main();

当我兴高采烈的提交代码后,居然跳出了,true ,false, false。于是我检查了代码,原来,111这样的算两个,我这样写的话只能算一个,好了找到问题了。那就修改一下匹配规则,给它加上正向肯定预查/(?=(11))/g,让‘111’这样的字符算两个。

修改后代码:

function solution(N) {
    let str = '';
    for (let i = 1; i <= N; i++) {
        str += i;
    }
    // 使用正则表达式匹配非重叠的子字符串“11”
    const matches = str.match(/(?=(11))/g);
    // 处理匹配结果,返回匹配的次数
    return matches ? matches.length : 0;
}

function main() {
    console.log(solution(11) === 1); // 输出: true
    console.log(solution(100) === 2); // 输出: true
    console.log(solution(111) === 6); // 输出: true
}

main();

ok,试一下。

image.png 非常的完美

然后就可以让ai转换语言进行提交了

好了,中等题写完了,接下来登场的是卡牌翻面求和问题。

第二题——卡牌翻面求和问题

这是一道困难题,我们先来看看题目

问题描述

小M有 𝑛n 张卡牌,每张卡牌的正反面分别写着不同的数字,正面是 𝑎𝑖ai​,背面是 𝑏𝑖bi​。小M希望通过选择每张卡牌的一面,使得所有向上的数字之和可以被3整除。你需要告诉小M,一共有多少种不同的方案可以满足这个条件。由于可能的方案数量过大,结果需要对 109+7109+7 取模。

例如:如果有3张卡牌,正反面数字分别为 (1,2)(2,3) 和 (3,2),你需要找到所有满足这3张卡牌正面或背面朝上的数字之和可以被3整除的组合数。


测试样例

样例1:

输入:n = 3 ,a = [1, 2, 3] ,b = [2, 3, 2]
输出:3

样例2:

输入:n = 4 ,a = [3, 1, 2, 4] ,b = [1, 2, 3, 1]
输出:6

样例3:

输入:n = 5 ,a = [1, 2, 3, 4, 5] ,b = [1, 2, 3, 4, 5]
输出:32

解题:

分析完题目发现卡牌的数字正反面是给定的,我们可以看作每张卡牌为两种可能的贡献值 𝑎 𝑖 a i ​ (正面)或 𝑏 𝑖 b i ​ (背面),并且希望最终选择的数字和对 3 取余后为 0。

可以使用动态规划来解决这个问题。对于每一张卡牌 i,我们有两种选择:可以选择它的正面 a[i-1] 或者背面 b[i-1]。如果选择了正面,那么新的和模3的结果就是 (当前和 + a[i-1]) % 3;如果选择了背面,则新的和模3的结果就是 (当前和 + b[i-1]) % 3。因此,我们可以根据上一步的状态 dp[i-1][j] 来更新 dp[i][j]。

具体来说,如果我们想要得到 dp[i][(j + a[i-1]) % 3] 的值,可以通过加上 dp[i-1][j] 来实现,因为这是通过将第 i 张卡牌的正面加入到之前总和为 j 的情况中得到的。同理,也可以通过将背面加入来更新相应的状态。

看看代码怎么实现的:

function solution(n, a, b) {
    const MOD = 10**9 + 7;
    
    // dp[i][j] 表示前 i 张卡牌选择后和对 3 取余为 j 的方案数
    let dp = new Array(n + 1).fill(0).map(() => new Array(3).fill(0));
    dp[0][0] = 1;  // 初始状态,没有卡牌时和为0的方案数为1
    
    // 遍历每张卡牌
    for (let i = 1; i <= n; i++) {
        for (let j = 0; j < 3; j++) {
            // 对每一张卡牌,选择正面或者背面
            dp[i][j] = (dp[i-1][(j - a[i-1] % 3 + 3) % 3] + 
                        dp[i-1][(j - b[i-1] % 3 + 3) % 3]) % MOD;
        }
    }
    
    // 返回最后一张卡牌选择后的和为0的方案数
    return dp[n][0];
}

// 测试用例
console.log(solution(3, [1, 2, 3], [2, 3, 2]) === 3);  // true
console.log(solution(4, [3, 1, 2, 4], [1, 2, 3, 1]) === 6);  // true
console.log(solution(5, [1, 2, 3, 4, 5], [1, 2, 3, 4, 5]) === 32);  // true

运行一下,

image.png

ok,完美解决。

好了,今天的分享就到这里了。