860. 柠檬水找零
1. first idea
就模拟找零钱就可以。 但是要注意一下顺序(有用例没过,所以才想到)。
对于20的bill,我们应该优先找零10+5,而不是5+5+5. 不然5容易不够用。
所以贪心的关键是每次找零优先找最大面额的零钱。
class Solution:
def lemonadeChange(self, bills: List[int]) -> bool:
cash_dict = {}
for bill in bills:
# 先试试能不能找开
if bill == 20:
if (cash_dict.get(5, 0) >= 1) and (cash_dict.get(10, 0) >= 1):
cash_dict[bill] = cash_dict.get(bill, 0) + 1
cash_dict[5] = cash_dict[5] - 1
cash_dict[10] = cash_dict[10] - 1
elif cash_dict.get(5, 0) >= 3:
# 如果可以就找开
cash_dict[bill] = cash_dict.get(bill, 0) + 1
cash_dict[5] = cash_dict[5] - 3
else:
print(cash_dict)
return False
if bill == 10:
if cash_dict.get(5, 0) >= 1:
cash_dict[bill] = cash_dict.get(bill, 0) + 1
cash_dict[5] = cash_dict[5] - 1
else:
print(cash_dict)
return False
if bill == 5:
cash_dict[bill] = cash_dict.get(5, 0) + 1
return True
406. 根据身高重建队列(理解起来比较难)
1. doc reading
class Solution:
def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]:
# 身高由高到低排序
people.sort(key=lambda x: (-x[0], x[1]))
queue = []
for idx in range(len(people)):
person_idx = people[idx][1]
queue.insert(person_idx, people[idx])
return queue
首先是要按照两级排序:
- 身高h降序,
- 前面比它高的个数k升序。
得到一个有序数组。
这个有序数组按照k进行插入,如果两个元素k相等,那么身高矮的应该排在身高较高的左侧,这样才能让矮个子的k满足。
而直接根据k将当前person插入结果队列恰好能满足这一要求。
因为如果结果队列长度还没超过k,那么这个person肯定插在了队尾,而哪个person插在队尾是受到之前sort影响的。
总结一下就是,矮个子排在哪都对高个子没有影响,但是高个子排在矮个子前面就会造成影响。所以,矮个子要主动选择位置。
452. 用最少数量的箭引爆气球
1. first idea
射每一个气球的右侧边界, 每射中一个气球,就将这个气球抹去。
局部最优:只要气球重叠就一起射 全局最优:所有气球都爆掉时射箭次数最少。
能做到一起射气球,只有两种方法:
- 要么从左向右遍历,找每个气球的最小右边界;
- 要么从右向左遍历,找每个气球的最大左边界。
否则会率先将重叠的气球中突出的单个区域对应的气球射爆,而非重叠起来。
class Solution:
def findMinArrowShots(self, points: List[List[int]]) -> int:
# 先搞个优先队列吧,根据每个点的第二个坐标值对点进行排序。
points.sort(key=lambda x: x[1])
count_int = 0
while points:
right_border = points[0][1]
points = points[1:]
count_int += 1
while points and (points[0][0] <= right_border <= points[0][1]):
points = points[1:]
return count_int
超出时限。
doc reading
class Solution:
def findMinArrowShots(self, points: List[List[int]]) -> int:
# 先搞个优先队列吧,根据每个点的第二个坐标值对点进行排序。
points.sort(key=lambda x: x[1])
count_int = 1
for idx in range(1, len(points)):
if points[idx][0] > points[idx - 1][1]:
count_int += 1
else:
points[idx][1] = min(points[idx][1], points[idx - 1][1])
return count_int
不需要真的删除,而是顺次遍历后,只要重叠,就将新的右边界更新为重叠的几个气球中最小右边界。