写代码的第二十五天
继续贪心!!gogogo!
134. 加油站
思路
贪心算法总让我有种脑子知道每次怎么计算,但是写不出来,也想不出贪心贪在哪里了,就只是觉得应该这么做。。。。。
本题中大家可以按照自己的计算方法一步一步模拟一下这个过程,然后会发现其实每次都是要计算每站剩余的油量,统计每一次的剩余油量然后累加计算,如果这个累加油量小于零那么就证明这个点之前的所有的点包括这个点都不满足走一圈的条件,从这个点之后的点继续向后遍历。
错误第一版:测试用例没通过,cursum在发现小于零的时候应该归零,因为从新开始的点开始遍历,累加和也要重新开始。
class Solution:
def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
start = 0
cursum = 0
for i in range(len(gas)):
cursum += (gas[i]-cost[i])
if cursum < 0:
start = i + 1
if cursum < 0:
return -1
return start
正确代码:
class Solution:
def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
start = 0
cursum = 0
totalsum = 0
for i in range(len(gas)):
cursum += (gas[i]-cost[i])
totalsum += (gas[i]-cost[i])
if cursum < 0:
start = i + 1
cursum = 0
if totalsum < 0:
return -1
return start
135. 分发糖果
思路
本题的要求是每个小孩最少一块糖,相邻的小孩分高的糖要更多,问怎么能用最少的糖果满足这个条件。可以分成两部分解决这个问题,从左向右和从右向左两个方向分别计算。初始化所有孩子的糖果都为1.
从左向右:如果右侧比左侧的分高,那么右侧应该在左侧的糖果的基础上加一;如果右侧小于等于左侧,那么右侧糖果数为1.
从右向左:在上述从左向右的基础上就是已经满足了右侧大于左侧的情况的糖果数量,现在要比较左侧比右侧大的时候的糖果数量,在上述糖果数量的基础上,如果左侧比右侧的糖果数量大,那么要在右侧糖果的基础上加一,需要注意一个问题如果这个时候的加一之后的值小于上一步计算之后的值,那么我们要保留最大的那个(只有保留最大的那个,才能满足左到右和右到左两部分);如果左侧小于等于右侧的糖果数量,此时不能设置左侧为1,如果设置为1,那么之前从左向右的计算就没有意义了,所以应该保持之前的到的值不变。
正确代码:
class Solution:
def candy(self, ratings: List[int]) -> int:
candy = [1] * len(ratings)
for i in range(len(ratings)):
if i > 0 and ratings[i] > ratings[i-1]:
candy[i] = candy[i-1] + 1
for i in range(len(ratings)-2,-1,-1):
if ratings[i] > ratings[i+1]:
candy[i] = max(candy[i+1] + 1,candy[i])
return sum(candy)
860.柠檬水找零
思路
题意只有5 10 20这三种情况的钱,所以根据这三种情况进行找零分析:
1、收到5的时候:直接收下,不用找零;
2、收到10的时候:如果有5,那么正常找零;如果没有5那么无法找零,失败;
3、收到20的时候:如果有一张10,一张5,那么正常找零;如果没有10,但是有三张5,也可以正常找零;如果不满足上面俩条件,那么失败。
(为什么要先判断有没有10,因为对于10来说只能对20进行找零,其他的时候没用,而5可以对10也可以对20找零,用处更广。)
正确代码:
class Solution:
def lemonadeChange(self, bills: List[int]) -> bool:
five = 0
ten = 0
for i in range(len(bills)):
if bills[i] == 5:
five += 1
elif bills[i] == 10:
if five:
five -= 1
ten += 1
else:
return False
elif bills[i] == 20:
if ten and five:
ten -= 1
five -= 1
elif five >= 3:
five -= 3
else:
return False
return True
406.根据身高重建队列
思路
本题有两个维度h和k,首先要决定 先排哪个维度?
如果先排k:以这个为例people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]],按照从小到大的顺序people=[[7,0].[5,0],[7,1],[6,1],[5,2],[4,4]],在这个顺序的基础上排h,然后会发现排完k对排h没有任何帮助,还是要手动一点一点调(动手写一下就明白了,这次排序没起到任何作用),没有任何可以插入的规律。
如果先排h:以这个为例people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]],按照从大到小的顺序(因为二维数组中的数据代表的就是前面有k个大于等于h的数据,所以从大到小排更方便)people=[[7,0],[7,1],[6,1],[5,0],[5,2],[4,4]],在这个顺序的基础上排k,此时70和71都满足题条件,61不满足条件,但是按照我们的排序顺序将61插入到下标为1的位置就可以了,因为h的顺序是已经排完的,所以是在有序的基础上只要将前面比他大于等于的数字满足k就行,排序之后的顺序是70 61 71,在看50也不满足所以将50插入到下标为0的点就行了,排序之后的顺序是50 70 61 71,再看52,将其插入到下标为2的位置就行了,排序之后的顺序是50 60 52 61 71,最后是44也不满足条件,将44插入到下标为4的位置即可,50 60 52 61 44 71,与最后的输出结果一致。
正确代码:这个题对我来说代码难得部分在people = sorted(people, key=lambda x: (-x[0], x[1])),以及queue.insert(position,people[i])。语法要记住。
解释一下为什么是position = people[i][1],我们是按照下标位置插入的,看上面写的思路中比如44也不满足条件,将44插入到下标为4的位置即可,我们是按照k的位置进行插入的,所以i代表的是在people这个数组中的哪个数组需要插入进queue(比如【4,4】),1代表的是people数组中第i位数组中的下标为1的数字,这个数字才是我们要在queue中插入的位置(【4,4】中的第二个4)。
class Solution:
def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]:
people = sorted(people, key=lambda x: (-x[0], x[1]))
queue = []
for i in range(len(people)):
position = people[i][1]
queue.insert(position,people[i])
return queue
标签:return,people,int,随想录,List,找零,柠檬水,糖果
From: https://blog.csdn.net/MYSTICSHUN/article/details/140812131