豆包MarsCode AI刷题(一)

80 阅读4分钟

今天给大家分享一下每日刷题的题目解析和经验分享,本系列预计会推出五期,今天给大家带来的是第一期的分享。

第一题——数组元素之和最小化


问题描述

小C希望构造一个包含n个元素的数组,且满足以下条件:

  1. 数组中的所有元素两两不同。
  2. 数组所有元素的最大公约数为 k
  3. 数组元素之和尽可能小。

任务是输出该数组元素之和的最小值。

测试样例

样例1:

输入:n = 3 ,k = 1
输出:6

样例2:

输入:n = 2 ,k = 2
输出:6

样例3:

输入:n = 4 ,k = 3
输出:30

解决方案

  1. 理解最大公约数(GCD)

    • 数组中的所有元素的最大公约数为 k,意味着每个元素都可以表示为 k 的倍数。
    • 因此,数组中的每个元素可以表示为 k * i,其中 i 是一个正整数。
  2. 构造数组

    • 为了满足数组元素两两不同且和最小,我们可以从 k 开始,依次选择 k, 2k, 3k, ..., nk 作为数组的元素。
    • 这样构造的数组满足所有元素两两不同,且最大公约数为 k
  3. 计算数组元素之和

    • 数组元素之和为 k + 2k + 3k + ... + nk
    • 这个和可以表示为 k * (1 + 2 + 3 + ... + n)
    • 根据等差数列求和公式,1 + 2 + 3 + ... + n = n * (n + 1) / 2
    • 因此,数组元素之和为 k * n * (n + 1) / 2

总结

我们可以构造出一个满足条件的数组,并且计算出数组元素之和的最小值。这个最小值可以通过公式 k * n * (n + 1) / 2 直接计算得出。

public class Main {
    public static int solution(int n, int k) {
        // 代码实现如下:
        int result = 0;
        for (int i = 1; i <= n; i++) {
            result += i*k;
        }
        return result;
    }
    // 测试用例如下:
    public static void main(String[] args) {
        System.out.println(solution(3, 1) == 6);
        System.out.println(solution(2, 2) == 6);
        System.out.println(solution(4, 3) == 30);
    }
}

复杂度分析


时间复杂度
  • 时间复杂度O(n)

    • 代码中包含一个 for 循环,循环次数为 n,因此时间复杂度为 O(n)
空间复杂度
  • 空间复杂度O(1)

    • 代码中只使用了常数个额外变量(result 和 i),没有使用额外的数据结构,因此空间复杂度为 O(1)

第二题——找单独的数


问题描述

在一个班级中,每位同学都拿到了一张卡片,上面有一个整数。有趣的是,除了一个数字之外,所有的数字都恰好出现了两次。现在需要你帮助班长小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
  • 班级人数为奇数
  • 除了一个数字卡片只出现一次外,其余每个数字卡片都恰好出现两次

解决方案

我们需要在一个整数数组中找到那个只出现一次的数字。数组中的其他数字都恰好出现两次。

数据结构的选择

由于题目要求时间复杂度为 O(n),并且尽量减少额外空间的使用,我们可以利用异或(XOR)操作的特性来解决这个问题。

异或操作的特性
  1. 相同数字的异或:对于任何整数 xx ^ x = 0。这意味着如果一个数字出现两次,它们异或的结果将是 0。
  2. 与 0 的异或:对于任何整数 xx ^ 0 = x。这意味着如果一个数字只出现一次,它与 0 异或的结果将是它本身。
算法步骤
  1. 初始化结果变量:我们初始化一个变量 result 为 0,用于存储异或操作的结果。
  2. 遍历数组:我们遍历数组中的每一个数字。
  3. 异或操作:对每一个数字进行异或操作,并将结果存储在 result 中。
  4. 返回结果:最终,result 中存储的就是那个单独的数字。

总结

通过利用异或操作的特性,我们可以在 O(n) 的时间复杂度内找到那个只出现一次的数字,并且不需要额外的空间。

public class Main {
    public static int solution(int[] cards) {
        // 代码实现如下:
        int result = 0;
        for (int card : cards) {
            result ^=card;
        }
        return result;
    }
    // 测试用例如下:
    public static void main(String[] args) {
        System.out.println(solution(new int[]{1, 1, 2, 2, 3, 3, 4, 5, 5}) == 4);
        System.out.println(solution(new int[]{0, 1, 0, 1, 2}) == 2);
        System.out.println(solution(new int[]{7, 3, 3, 7, 10}) == 10);
    }
}