代码随想录算法训练营第二十九天 |贪心算法part03

90 阅读2分钟

代码随想录算法训练营第二十九天 |贪心算法part03

134 加油站

image.png

思路:分成两步,第一步是看当前油量,第二步看总油量。

当前油量如果小于0,那么肯定就不能从这次的开头开始。如果总油量小于0,说明走不完。

curgas = 0
totalgas = 0
start = 0
for i in range(len(gas)):
    curgas += gas[i] - cost[i]
    totalgas += gas[i] - cost[i]
    if curgas < 0 :
        start = i + 1
        curgas = 0
if totalgas < 0 :
    return -1 
return start

135 分发糖果

image.png

思路:分成两次发,第一次从左往右发,第二次从右往左发。

ratings = [1,2,87,87,87,2,1]
candys = [1] * len(ratings)
# 从左往右数,左边的比右边的小
for i in range(1,len(ratings)):
    if ratings[i] > ratings[i-1] :
        candys[i] = candys[i-1] + 1
print(candys)
# 从右往左数,左边的比右边的大
for i in range(len(ratings)-2,-1,-1):
    if ratings[i] > ratings[i+1] :
        # print(i,candys)
        candys[i] = max(candys[i],candys[i+1]+1) 
print(candys)
print(sum(candys))

860 柠檬水找零

image.png

思路:这道题目很简单,直接记录每一种钞票对应的数量就可以了。

bills = [5,5,10,10,20]
five = 0
ten = 0
twenty = 0
for i in bills:
    if i == 5:
        five += 1
    elif i == 10:
        five -= 1
        ten += 1
    elif i == 20:
        if ten > 0 and five > 0:
            ten -= 1
            five -= 1
        else:
            five -= 3
    if five < 0 or ten < 0:
        print(False)
print(True)

406 根据身高重建队列

image.png

思路:列表中元素的第一位是身高,第二位是前面的人身高比他高或一样高的人数。 所以这道题目就转换成了按照第二位进行排序的问题。 首先根据身高进行排序,如果身高相同,那么第二位小的排在前面。 其次按照上一步的列表进行插入到新的列表。

按照身高排序之后,优先按身高高的people的k来插入,后序插入节点也不会影响前面已经插入的节点,最终按照k的规则完成了队列。

也就是按照排序后的列表的第二位进行插入,按顺序遍历该列表,插入到新的列表的位置(索引)就是对应的第二位

所以在按照身高从大到小排序后:

局部最优:优先按身高高的people的k来插入。插入操作过后的people满足队列属性

全局最优:最后都做完插入操作,整个队列满足题目队列属性

insert(i,j) :在索引为i处插入元素j

people.sort(key=lambda x: (-x[0], x[1]))
people.sort(key=lambda x: (x[0],-x[1]), reverse=True)
que = []
for p in people:
    que.insert(p[1], p)
return que