2 / 6 第一题问题描述
小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)。这个算法的时间复杂度为O(n),空间复杂度为O(1),非常适合解决这个问题。
解题思路
- 理解问题:我们需要找到数组中出现次数超过一半的数字。
- 摩尔投票算法:
- 初始化两个变量:
candidate和count。candidate用于存储当前候选数字,count用于记录当前候选数字的计数。 - 遍历数组中的每个元素:
- 如果
count为 0,将当前元素设为candidate,并将count设为 1。 - 如果当前元素与
candidate相同,count加 1。 - 如果当前元素与
candidate不同,count减 1。
- 如果
- 最终
candidate就是出现次数超过一半的数字。
- 初始化两个变量:
代码
def solution(array):
# 初始化 candidate 和 count
candidate = None
count = 0
# 遍历数组
for num in array:
# 如果 count 为 0,更新 candidate
if count == 0:
candidate = num
count = 1
# 如果当前元素与 candidate 相同,count 加 1
elif num == candidate:
count += 1
# 如果当前元素与 candidate 不同,count 减 1
else:
count -= 1
# 返回 candidate
return candidate
if __name__ == "__main__":
# 测试样例
print(solution([1, 3, 8, 2, 3, 1, 3, 3, 3]) == 3)
print(solution([5, 5, 5, 1, 2, 5, 5]) == 5)
print(solution([9, 9, 9, 9, 8, 9, 8, 8]) == 9)
解释
candidate和count用于跟踪当前的候选数字及其计数。- 通过遍历数组,算法能够有效地找到出现次数超过一半的数字。
2/ 6 第二题问题描述
小F最近迷上了玩一款游戏,她面前有一个永久代币卡的购买机会。该卡片的价格为 a 勾玉,每天登录游戏可以返还 b 勾玉。小F想知道她至少需要登录多少天,才能让购买的永久代币卡回本。
测试样例
样例1:
输入:
a = 10, b = 1
输出:10
样例2:
输入:
a = 10, b = 2
输出:5
样例3:
输入:
a = 10, b = 3
输出:4
-
理解问题:
- 需要计算小F需要登录多少天才能让购买的永久代币卡回本。
- 每天登录游戏可以返还
b勾玉。 - 需要计算出至少需要多少天,使得返还的勾玉总数等于或超过购买卡片的费用
a。
-
数学公式:
- 设需要的天数为
days。 - 每天返还
b勾玉,days天后返还的总勾玉数为days * b。 - 需要满足
days * b >= a。
- 设需要的天数为
-
求解公式:
- 从上面的不等式可以推导出
days >= a / b。 - 由于
days必须是整数,所以需要向上取整,即days = ceil(a / b)。
- 从上面的不等式可以推导出
-
代码实现:
- 可以使用 Python 的
math.ceil函数来实现向上取整。
- 可以使用 Python 的
import math
def solution(a: int, b: int) -> int:
# 计算需要的天数
days = math.ceil(a / b)
return days
if __name__ == '__main__':
print(solution(10, 1) == 10)
print(solution(10, 2) == 5)
print(solution(10, 3) == 4)
解释:
math.ceil(a / b)用于向上取整,确保days是一个整数。- 这个方法直接计算出需要的天数,并且满足题目要求。
2 / 6 第三题问题描述
小U得到了一个数字n,他的任务是构造一个特定数组。这个数组的构造规则是:对于每个i从1到n,将数字n到i逆序拼接,直到i等于n为止。最终,输出这个拼接后的数组。
例如,当n等于3时,拼接后的数组是 [3, 2, 1, 3, 2, 3]。
测试样例
样例1:
输入:
n = 3
输出:[3, 2, 1, 3, 2, 3]
样例2:
输入:
n = 4
输出:[4, 3, 2, 1, 4, 3, 2, 4, 3, 4]
样例3:
输入:
n = 5
输出:[5, 4, 3, 2, 1, 5, 4, 3, 2, 5, 4, 3, 5, 4, 5]
解题思路
-
理解问题:
- 你需要构造一个数组,对于每个
i从1到n,将数字n到i逆序拼接,直到i等于n为止。 - 例如,当
n = 3时,数组应该是[3, 2, 1, 3, 2, 3]。
- 你需要构造一个数组,对于每个
-
数据结构选择:
- 使用一个列表(数组)来存储最终的结果。
-
算法步骤:
- 初始化一个空列表
result。 - 使用一个循环从
1到n,对于每个i:- 生成从
n到i的逆序序列。 - 将这个逆序序列追加到
result中。
- 生成从
- 返回
result。
- 初始化一个空列表
伪代码框架
def solution(n: int) -> list:
result = [] # 初始化结果列表
for i in range(1, n + 1): # 从1到n循环
# 生成从n到i的逆序序列
for j in range(n, i - 1, -1):
result.append(j)
return result # 返回结果列表
if __name__ == '__main__':
print(solution(3) == [3, 2, 1, 3, 2, 3])
print(solution(4) == [4, 3, 2, 1, 4, 3, 2, 4, 3, 4])
print(solution(5) == [5, 4, 3, 2, 1, 5, 4, 3, 2, 5, 4, 3, 5, 4, 5])
关键步骤解释
-
初始化结果列表:
result = [] -
外层循环:
for i in range(1, n + 1): -
内层循环生成逆序序列:
for j in range(n, i - 1, -1): result.append(j) -
返回结果:
return result
以下是完整的代码:
def solution(n: int) -> list:
result = [] # 初始化结果列表
for i in range(1, n + 1): # 从1到n循环
# 生成从n到i的逆序序列
for j in range(n, i - 1, -1):
result.append(j)
return result # 返回结果列表
if __name__ == '__main__':
print(solution(3) == [3, 2, 1, 3, 2, 3])
print(solution(4) == [4, 3, 2, 1, 4, 3, 2, 4, 3, 4])
print(solution(5) == [5, 4, 3, 2, 1, 5, 4, 3, 2, 5, 4, 3, 5, 4, 5])
代码解释
-
初始化结果列表:
result = [] -
外层循环:
for i in range(1, n + 1): -
内层循环生成逆序序列:
for j in range(n, i - 1, -1): result.append(j) -
返回结果:
return result