贪心
找出整型数组中占比超过一半的数
问题描述
小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)。
超市里的货物架调整
问题描述
在一个超市里,有一个包含 个格子的货物架,每个格子中放有一种商品,商品用小写字母 a 到 z 表示。当顾客进入超市时,他们会依次从第一个格子查找到第 个格子,寻找自己想要购买的商品。如果在某个格子中找到该商品,顾客就会购买它并离开;如果中途遇到一个空格子,或查找完所有格子还没有找到想要的商品,顾客也会离开。
作为超市管理员,你可以在顾客到来之前重新调整商品的顺序,以便尽可能多地出售商品。当第一个顾客进入后,商品位置不能再调整。你需要计算在最优调整下,最多可以卖出多少件商品。输入变量说明:
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个元素的数组,且满足以下条件:
- 数组中的所有元素两两不同。
- 数组所有元素的最大公约数为
k。 - 数组元素之和尽可能小。
任务是输出该数组元素之和的最小值。
测试样例
样例1:
输入:
n = 3 ,k = 1输出:6
样例2:
输入:
n = 2 ,k = 2输出:6
样例3:
输入:
n = 4 ,k = 3输出:30
解题思路1
- 最大公约数为
k:这意味着数组中的每个元素都必须是k的倍数。 - 两两不同:我们需要确保数组中的元素是唯一的。
- 元素之和最小:为了使数组元素之和最小,我们可以从最小的
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。为了使元素之和尽可能小,可以选择最小的 n 个 k 的倍数:k, 2k, 3k, ..., nk。
推导公式
为了最小化数组元素之和,我们选择数组元素为 k, 2k, 3k, ..., nk,其和为:
sum = k×(1+2+3+...+n) = k×
代码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)