860. 柠檬水找零
遇到顾客给20块的,优先拿10块的找给他。
class Solution:def lemonadeChange(self, bills: List[int]) -> bool:change = {5: 0, 10: 0}for bill in bills:if bill == 5:change[5] += 1elif bill == 10:if change[5] < 1:return Falsechange[5] -= 1change[10] += 1else:if change[10] >= 1 and change[5] >= 1:change[10] -= 1change[5] -= 1elif change[5] >= 3:change[5] -= 3else:return Falsereturn True
406. 根据身高重建队列
我的思路:
AC了一个On^2的写法,
建一个哈希表,键为所有的身高,值为一个有序列表,以ki从小到大排序。对键值从小到大遍历,每次弹出列表尾元素,ki是多少,前面就留几个空,直到遍历完所有的元素。
class Solution:def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]:n = len(people)ht = collections.defaultdict(list)pos = [x for x in range(n)]res = [None] * npeople.sort()for person in people:ht[person[0]].append(person)for i in range(n):count = 0height = people[i][0]rank = ht[height].pop()[1]res[pos[rank]] = [height, rank]del pos[rank]return res
优化:
啊其实思路大概是对的了,哈希表套栈不是必要的,因为可以通过匿名函数实现身高升序、ki降序排序:
people.sort(key=lambda x:(x[0],-x[1]))
然后后续留空其实也是不必要的,可以用insert方法插值;我的方法是从低到高,把矮的按照前面有几个比他高的放到对应的位置。如果从高到低排序,先把高放下来,后面放矮的就是按照他的k值来放,矮的k只相对于前面已经放下的高的,所以从高到低放;相同高度就看k值,先放k小的,再放k大的,可以保证前面的是大于等于自己高度的。
代码:
class Solution:def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]:people.sort(key=lambda x:(-x[0], x[1]))res = []for person in people:res.insert(person[1], person)return res
就换了个排序顺序就差了这么多代码量,真的好壮观!!
452. 用最少数量的箭引爆气球
我的方法:
先排序,起始点和终点都是升序,然后对每一个point,计算他和之前所有的交集,如果某处没有交集了,就要多打一支箭,把交集置为新的point。
class Solution:def findMinArrowShots(self, points: List[List[int]]) -> int:arrows = 1points.sort()inter = points[0]print(points)for point in points:if point[0] > inter[1]:inter = pointarrows += 1else:inter[0] = max(inter[0], point[0])inter[1] = min(inter[1], point[1])return arrows
优化:
思路大概是一样的,其实用不着每次记录一个交集,只要记录边界即可。按照end升序排序,记录end,从第一个point开始,point的start如果小于等于记录的end,那么从start射一箭必可以引爆前面所有的气球;如果start大于end了,把end置为新的point的end,多加一枝箭。
class Solution:def findMinArrowShots(self, points: List[List[int]]) -> int:arrows = 1points.sort(key=lambda x: x[1])end = points[0][1]for i_start, i_end in points:if i_start > end:end = i_endarrows += 1return arrows
我的原始方法虽然逻辑上正确,但在处理每个气球时,尝试通过更新交集区间来最大程度地减少所需的箭数。这一步虽然在理论上能够为每次射箭找到一个最优的射击点,但实际上却增加了计算复杂度。题解方法提供了一个更为高效的视角,它通过将气球按照结束坐标进行排序,确保了我们总是在可能的最早点射出箭来引爆气球。在这个方法中,只有当遇到一个新的气球,且这个气球的起始坐标超过了当前箭能覆盖的最远距离时,才会增加箭的数量。这样的处理不仅简化了逻辑,还显著减少了计算量,因为它避免了不必要的每次交集更新,而仅在必要时更新箭的射击范围。
今日总结:
全AC了,但第二三题跟题解比起来都在运行速度上有所欠缺,思路仍然不是十分清晰,看到题解会有豁然开朗的感觉。