AI 刷题(四) | 豆包MarsCode AI刷题

167 阅读5分钟

贪心


找出整型数组中占比超过一半的数

问题描述

小R从班级中抽取了一些同学,每位同学都会给出一个数字。已知在这些数字中,某个数字的出现次数超过了数字总数的一半。现在需要你帮助小R找到这个数字。

测试样例

样例1:

输入:array = [1, 3, 8, 2, 3, 1, 3, 3, 3] 输出:3

样例2:

输入:array = [5, 5, 5, 1, 2, 5, 5] 输出:5

样例3:

输入:array = [9, 9, 9, 9, 8, 9, 8, 8] 输出:9

解题思路

要在一个整数数组中找到出现次数超过数组长度一半的元素。这种元素被称为“多数元素”。已知数组中一定存在这样的元素,我们可以利用 摩尔投票算法(Boyer-Moore Voting Algorithm)在一次遍历中找到这个多数元素。 摩尔投票算法的核心思想是:在数组中逐一处理元素,通过维护一个计数器 count 来跟踪候选元素 candidate。若两个不同的元素配对,计数器会相互抵消;只有在遇到同样的元素时,计数器才会增加。因此,当遍历结束时,candidate 就会是数组中占比超过一半的元素。

代码

def solution(array):
    # Edit your code here
    count = 0
    candidate = None
    for num in array:
        if count == 0:
            candidate = num
        count += 1 if num == candidate else -1
    return candidate


if __name__ == "__main__":
    # Add your test cases here

    print(solution([1, 3, 8, 2, 3, 1, 3, 3, 3]) == 3)
  • 时间复杂度:O(n)。
  • 空间复杂度:O(1)。

超市里的货物架调整

问题描述

在一个超市里,有一个包含 nn 个格子的货物架,每个格子中放有一种商品,商品用小写字母 a 到 z 表示。当顾客进入超市时,他们会依次从第一个格子查找到第 nn 个格子,寻找自己想要购买的商品。如果在某个格子中找到该商品,顾客就会购买它并离开;如果中途遇到一个空格子,或查找完所有格子还没有找到想要的商品,顾客也会离开。

作为超市管理员,你可以在顾客到来之前重新调整商品的顺序,以便尽可能多地出售商品。当第一个顾客进入后,商品位置不能再调整。你需要计算在最优调整下,最多可以卖出多少件商品。输入变量说明:

  • n:货物架的格子数
  • m:顾客想要购买的商品种类数
  • s:货物架上商品的初始顺序
  • c:顾客想要购买的商品种类

测试样例

样例1:

输入:n = 3 ,m = 4 ,s = "abc" ,c = "abcd" 输出:3

样例2:

输入:n = 4 ,m = 2 ,s = "abbc" ,c = "bb" 输出:2

样例3:

输入:n = 5 ,m = 4 ,s = "bcdea" ,c = "abcd" 输出:4

算法步骤

  • 统计货架上每种商品的频率
  • 统计顾客需求中每种商品的频率
  • 计算最大销售量

代码

def solution(n: int, m: int, s: str, c: str) -> int:
    # 统计货架上每种商品的频率
    shelf_count = {}
    for item in s:
        shelf_count[item] = shelf_count.get(item, 0) + 1
    
    # 统计顾客需求中每种商品的频率
    demand_count = {}
    for item in c:
        demand_count[item] = demand_count.get(item, 0) + 1
    
    # 计算最大销售量
    sold = 0
    for item in demand_count:
        if item in shelf_count:
            sold += min(shelf_count[item], demand_count[item])
    
    return sold

if __name__ == '__main__':
    print(solution(3, 4, "abc", "abcd") == 3)
    print(solution(4, 2, "abbc", "bb") == 2)
    print(solution(5, 4, "bcdea", "abcd") == 4)
  • 时间复杂度:O(n+m)
  • 空间复杂度:O(k),其中 k 是货架上商品种类的数量

数组元素之和最小化

问题描述

小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

  1. 最大公约数为 k:这意味着数组中的每个元素都必须是 k 的倍数。
  2. 两两不同:我们需要确保数组中的元素是唯一的。
  3. 元素之和最小:为了使数组元素之和最小,我们可以从最小的 k 的倍数开始,逐步增加,直到数组中有 n 个元素。

代码1

def solution(n: int, k: int) -> int:
    # write code here
    current_number = k
    sum_of_elements = 0
    
    # 循环找到n个不同的k的倍数
    for _ in range(n):
        sum_of_elements += current_number
        current_number += k
    
    return sum_of_elements

if __name__ == '__main__':
    print(solution(n = 3, k = 1) == 6)
    print(solution(n = 2, k = 2) == 6)
    print(solution(n = 4, k = 3) == 30)

解题思路2

从条件 2 可以推断,数组中的每个元素都必须是 k 的倍数,这样整个数组的最大公约数就会是 k。为了使元素之和尽可能小,可以选择最小的 nk 的倍数:k, 2k, 3k, ..., nk

推导公式

为了最小化数组元素之和,我们选择数组元素为 k, 2k, 3k, ..., nk,其和为: sum = k×(1+2+3+...+n) = k×n×(n+1)2\frac{n×(n+1)}{2}

代码2

def solution(n: int, k: int) -> int:
    return k * n * (n + 1) // 2

if __name__ == '__main__':
    print(solution(n = 3, k = 1) == 6)
    print(solution(n = 2, k = 2) == 6)
    print(solution(n = 4, k = 3) == 30)