11月8日-11月10日刷题总结 | 豆包MarsCode AI刷题

110 阅读3分钟

11月8日 小E的射击训练

问题描述 

小E正在训练场进行射击练习,靶有10个环,靶心位于坐标(0, 0)。每个环对应不同的得分,靶心内(半径为1)得10分,依次向外的每个环分数减少1分。若射击点在某个半径为i的圆内,则得11-i分。如果射击点超出所有的环,则得0分。 根据给定的射击坐标(x, y),请计算小E的射击得分。 

思考

这道题我们只需要依次判断点是否位于半径从1到10的圆内。 找到点所在的第一个圆即返回对应的分数,无需继续判断。

代码

def solution(x: int, y: int) -> int:    # 计算距离平方    distance_sq = x * x + y * y        # 判断在哪个环内,半径从 110    for i in range(1, 11):        if distance_sq <= i * i:            return 11 - i        # 超出所有环得 0return 0

分析

本道题比较简单,属于经典的计算几何问题,考察对点与圆关系的理解和实现能力。 我们可以通过直接平方比较的方法,避免了不必要的浮点数误差。

11月9日 找出整型数组中占比超过一半的数

问题描述

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

思考

给定一个数组,要求找出一个数字,该数字出现的次数超过数组长度的一半。 根据题目描述,必然存在这样的数字。 最简单的方法是统计每个数字的出现次数,但这会消耗O(n) 的空间复杂度。我们这里使用使用 摩尔投票法(Boyer-Moore Voting Algorithm)。值得注意的是,虽然摩尔投票法可以找到候选数字,但仍需验证该数字的出现次数是否超过一半。

摩尔投票法(Boyer-Moore Voting Algorithm)是一种高效算法,用于在一组数据中找到 多数元素(出现次数超过数组长度一半的元素)。该算法利用计数抵消策略来确定候选元素,时间复杂度为O(n),空间复杂度为 O(1)。第一遍遍历需要我们确定候选元素: 使用计数器统计抵消过程,最终得到一个可能的候选元素。 第二遍遍历需要我们验证候选元素: 统计候选元素的实际出现次数,判断其是否超过数组长度的一半。

代码

def solution(array):    # 初始候选人设置为空,计数为0    candidate = None    count = 0    # 通过摩尔投票法找到候选元素    for num in array:        if count == 0:            candidate = num        count += 1 if num == candidate else -1    # 检查候选元素是否满足条件    if array.count(candidate) > len(array) // 2:        return candidate    else:        return None  # 如果不存在超过一半的元素

分析

  • 摩尔投票法的核心在于通过计数器抵消掉不可能的候选人,最终找到潜在的候选数字。 只需两次遍历即可完成,效率高且实现简洁。

摩尔投票法的优雅之处在于通过“抵消”减少无关元素的影响,而不需要额外的存储和复杂计算。它的本质利用了多数元素的数学性质,提供了一种高效而直观的解决方案。

11月10日 小R的随机播放顺序

问题描述 

小R有一个特殊的随机播放规则。他首先播放歌单中的第一首歌,播放后将其从歌单中移除。如果歌单中还有歌曲,则会将当前第一首歌移到最后一首。这个过程会一直重复,直到歌单中没有任何歌曲。 

 例如,给定歌单 [5, 3, 2, 1, 4],真实的播放顺序是 [5, 2, 4, 1, 3]。 保证歌曲中的id两两不同。

思路

在这道题,我们通过列表的动态操作,模拟了题目中 "播放第一首" 和 "移到最后一首" 的规则,按逻辑构造播放顺序。pop 和 append 的结合非常适合这种“移除+重排”的操作模式。

代码

def solution(n: int, a: list) -> list:    result = []    while a:        # 播放第一首歌并移除        result.append(a.pop(0))        # 将当前第一首歌移到最后一首(如果还有歌)        if a:            a.append(a.pop(0))    return result

分析代码知识点

  • list.pop(0):移除列表中的第一个元素并返回其值。pop 是一种修改性操作,时间复杂度为 O(n),因为它需要将剩余元素向前移动。 
  • list.append(x):将元素添加到列表末尾,时间复杂度为 O(1)。

通过这道题,我学会了如何结合逻辑和数据结构设计高效的算法,进一步巩固了对列表操作的理解。