第六周 贪心专题
122 买卖股票的最佳时机 II
[7,1,5,3,6,4] 2号买入3号卖出赚4,3买入6卖出赚3。买入后只能卖出不能买入。虽然题目说不可以一天内多次操作,但写代码是可以的,这不会影响最终结果。因此考虑,[1,2,3]不仅是1号买入3号卖出,也可以是1号买入2号卖出2号买入3号卖出,这样就可以使用遍历。
看到答案里最简单的方法:一行python解决。可以细化到相邻两天的差价,正则赚,进行操作,负则不操作,即记录正值的和。
class Solution:
def maxProfit(self, prices: List[int]) -> int:
return sum(b-a for a,b in zip(prices, prices[1:]) if b>a)
134 加油站
环路,n个加油站点存储着油,过去要消耗油。注意要遍历可以使用余数!当cur+1=start时遍历结束。如果当前节点到不了下一个,就把起点往前挪一个。不然就加油进入下一个。返回时考虑能否到起点,这是个坑。
class Solution:
def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
n = len(gas)
start, cur = 0, 0
oil = gas[0]
while (cur + 1) % mod != start:
if oil < cost[cur]:
start = (start - 1) % n
oil += gas[start] - cost[start]
else:
oil -= cost[cur]
cur = (cur + 1) % n
oil += gas[cur]
return start if oil - cost[cur] >= 0 else -1
55 跳跃游戏
一个数组,每个数值代表当前位置最大跳跃距离,判断能否跳到最后。贪心:希望跳到最远的地方。注意,能够达到某处,则前面的位置一定能够到达。所以,存储当前能够到达的最远距离,与最终结果位置做比较,如果maxDist比len(nums)-1也就是最后一个元素的位置还远,那么就能到终点。
class Solution:
def canJump(self, nums: List[int]) -> bool:
if nums==[0]: return True
terminal = len(nums)-1
maxDist = 0
for i, jump in enumerate(nums):
if i <= maxDist and i+jump > maxDist:
maxDist = i+jump
if maxDist >= terminal:
return True
return False
435 无重叠区间
[[1,2],[2,3],[1,3]]时删除第三个元素可以得到无重叠区间的最长子序列。要返回需要删除元素的最少个数,所以贪心算法,尽量保留跨度小,或者说右侧数字较小的元素,因此需要对右侧数字进行排序。排序后如果下一个元素开始数字比当前元素结束数字小则删掉,或者说反向思考,下一个元素起点比当前的终点大于等于才保留。
class Solution:
def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
n = len(intervals)
save = 0
intervals.sort(key=lambda x:x[1])
end = -float('inf')
for interval in intervals:
start = interval[0]
if start >= end:
save += 1
end = interval[1]
return n-save
406 根据身高重建队列
没看懂题目
649 Dota2参议院
'RD’互ban,则RbanD,则R胜。‘RDD’则D胜。贪心算法:己方ban的权利碰到敌方的时候就使用 先后使用结果一样 那么无限循环直到只有一方那就结束了。
class Solution:
def predictPartyVictory(self, senate: str) -> str:
senate = list(senate) # list才可在后面赋值,改变元素
people = 0 # 通过正负分辨两方
Radiant, Dire = True, True
while Radiant and Dire: # 直至一方阵亡
Radiant, Dire = False, False
for i in range(len(senate)):
if senate[i] == 'R':
Radiant = True # 己方有人
if people < 0: # 被对方ban了
senate[i] = '0' # 下次检索不到了
people += 1
if senate[i] == 'D':
Dire = True
if people>0:
senate[i] = '0'
people -= 1
if people > 0 : return 'Radiant' # 判断存活方
if people < 0 : return 'Dire'
402 移掉k位数字
输入num,移走k位数字,希望得到的数字最小,但返回的是字符串,且不可以有0。贪心算法,从左往右,遇到小的就把大的去掉,形成递增序列,肯定是前面小则整体小。
class Solution:
def removeKdigits(self, num: str, k: int) -> str:
res = []
for ele in num:
while k and res and res[-1]>ele:
res.pop()
k -= 1
res.append(ele)
res = res[:-k] if k else res # res递增,还剩下k个没删除,则从后面开始删
return ''.join(res).lstrip('0') or '0' # 空字符串用‘0’代替