暴力解法O(n^2):
class Solution:
def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
for i in range(len(gas)):
rest = gas[i] - cost[i]
index = (i+1) % len(gas)
while rest > 0 and index != i:
rest += gas[index] - cost[index]
index = (index + 1) % len(gas)
if rest >= 0 and index == i:
return i
return -1
贪心算法:
首先如果总油量减去总消耗大于等于零那么一定可以跑完一圈,说明 各个站点的加油站 剩油量rest[i]相加一定是大于等于零的。
i从0开始累加rest[i],和记为curSum,一旦curSum小于零,说明[0, i]区间都不能作为起始位置,因为这个区间选择任何一个位置作为起点,到i这里都会断油,那么起始位置从i+1算起,再从0计算curSum。
那么为什么一旦[0,i] 区间和为负数,起始位置就可以是i+1呢,i+1后面就不会出现更大的负数?如果出现更大的负数,就是更新i,那么起始位置又变成新的i+1了。
那么局部最优:当前累加rest[i]的和curSum一旦小于0,起始位置至少要是i+1,因为从i之前开始一定不行。全局最优:找到可以跑一圈的起始位置。
class Solution:
def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
curSum = 0
totalSum = 0 #用来判断是否会出现跑完一整个环都不行的情况
start = 0 #记录出发时的加油站
for i in range(len(gas)):
rest = gas[i] - cost[i]
curSum += rest
totalSum += rest
if curSum < 0:
start = i + 1
#重置curSum
curSum = 0
if totalSum < 0: # 总剩余油量totalSum小于0,说明无法环绕一圈
return -1
return start
难点就在于贪心的策略,如果在考虑局部的时候想两边兼顾,就会顾此失彼。
那么本题我采用了两次贪心的策略:
- 一次是从左到右遍历,只比较右边孩子评分比左边大的情况。
- 一次是从右到左遍历,只比较左边孩子评分比右边大的情况。
这样从局部最优推出了全局最优,即:相邻的孩子中,评分高的孩子获得更多的糖果
class Solution:
def candy(self, ratings: List[int]) -> int:
#从前往后遍历,处理右侧评分比左侧高的情况
candy = [1] * len(ratings)
for i in range(1, len(ratings)):
if ratings[i] > ratings[i-1]:
candy[i] = candy[i-1] + 1
#从后往前比较
for j in range(len(ratings)-2, -1, -1): #起始的边界不检查
if ratings[j] > ratings[j+1]:
candy[j] = max(candy[j], candy[j+1] + 1)
return sum(candy)
注意,此题中只有三种面额的钞票,要根据钞票数量来做
class Solution:
def lemonadeChange(self, bills: List[int]) -> bool:
five_remain = 0
ten_remain = 0
twenty_remain = 0
for bill in bills:
if bill == 5:
five_remain += 1
elif bill == 10:
if five_remain < 1:
return False
else:
five_remain -= 1
ten_remain += 1
elif bill == 20:
if five_remain >= 1 and ten_remain >= 1:
five_remain -= 1
ten_remain -= 1
twenty_remain += 1
elif five_remain >= 3:
five_remain -= 3
twenty_remain += 1
else:
return False
return True
class Solution:
def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]:
queue = []
#先进行初步排序,再使用贪心算法进行调整
#hi大的排前面,ki大的排后面
people.sort(key = lambda x:(-x[0], x[1]))
#记住这一步的做法
for p in people:
queue.insert(p[1], p)
return queue