1)435.五重叠区域
435. 无重叠区间 - 力扣(LeetCode) (leetcode-cn.com)
class Solution:
def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
intervals.sort(key=lambda x: x[1])
endval=intervals[0][1]
res=1
for i in intervals[1:]: #改为计算不重叠区
if endval<= i[0]:
endval = i[1]
res+=1
return len(intervals) - res
2)763.划分字母区间
763. 划分字母区间 - 力扣(LeetCode) (leetcode-cn.com)
class Solution:
def partitionLabels(self, s: str) -> List[int]:
#首先遍历最远位置 从右向左遍历
n= len(s)
fnum=[n]*n
for i in range(n-2,-1,-1):
findex=s[i+1:].find(s[i])
if findex+1:fnum[i]=fnum[findex+i+1]
else:fnum[i] = i+1
#然后把最远位置删选出来
left,right = 0,0
res=[]
for i in range(n):
if fnum[i] > right: right=fnum[i]
if not right-i-1:
res.append(right-left)
left=right
return res
3)56.合并区间
56. 合并区间 - 力扣(LeetCode) (leetcode-cn.com)
这道题和之前做的某道题还是挺像的
class Solution:
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
intervals.sort()
res= [intervals[0]]
for i in intervals:
if res[-1][1] < i[0]: res.append(i)
else:res[-1][1]=max(i[1],res[-1][1])
return res
4)738. 单调递增的数字
738. 单调递增的数字 - 力扣(LeetCode) (leetcode-cn.com)
class Solution:
def monotoneIncreasingDigits(self, n: int) -> int:
n= list(str(n))
for i in range(len(n)-2,-1,-1):
if n[i] > n[i+1]:
n[i]=str(int(n[i])-1)
n[i+1:]='9'*(len(n)-i-1) #从后向前遍历只要出现9 就把后面全部变为9
return int(''.join(n))
5)714. 买卖股票的最佳时机含手续费
714. 买卖股票的最佳时机含手续费 - 力扣(LeetCode) (leetcode-cn.com)
class Solution:
def maxProfit(self, prices: List[int], fee: int) -> int:
minprice= prices[0]
res = 0
for i in prices:
if i< minprice: minprice=i #买入
if minprice <= i <=minprice+fee:continue #保持持有
if minprice +fee < i: #卖出
res+=i-minprice-fee
minprice= i-fee #这一步很关键,因为这不一定是真的卖掉了 当出现i大于的情况还可以再卖一次,直到买入把他覆盖掉,才是真的卖掉了
return res
6)968.监控二叉树
968. 监控二叉树 - 力扣(LeetCode) (leetcode-cn.com)
这里定义了三个状态
0:该节点无覆盖
1:本节点有摄像头
2:本节点有覆盖
分别用前面的数字表示,
且应该用后序遍历,也就是左右中的方式
有递归和迭代两种算法,
class Solution:
def minCameraCover(self, root: TreeNode) -> int:
# Greedy Algo:
# 从下往上安装摄像头:跳过leaves这样安装数量最少,局部最优 -> 全局最优
# 先给leaves的父节点安装,然后每隔两层节点安装一个摄像头,直到Head
# 0: 该节点未覆盖
# 1: 该节点有摄像头
# 2: 该节点有覆盖
result = 0
# 从下往上遍历:后序(左右中)
def traversal(curr: TreeNode) -> int:
nonlocal result
if not curr: return 2
left = traversal(curr.left)
right = traversal(curr.right)
# Case 1:
# 左右节点都有覆盖
if left == 2 and right == 2:
return 0
# Case 2:
# left == 0 && right == 0 左右节点无覆盖
# left == 1 && right == 0 左节点有摄像头,右节点无覆盖
# left == 0 && right == 1 左节点有无覆盖,右节点摄像头
# left == 0 && right == 2 左节点无覆盖,右节点覆盖
# left == 2 && right == 0 左节点覆盖,右节点无覆盖
elif left == 0 or right == 0:
result += 1
return 1
# Case 3:
# left == 1 && right == 2 左节点有摄像头,右节点有覆盖
# left == 2 && right == 1 左节点有覆盖,右节点有摄像头
# left == 1 && right == 1 左右节点都有摄像头
elif left == 1 or right == 1:
return 2
# 其他情况前段代码均已覆盖
if traversal(root) == 0: #处理头节点
result += 1
return result
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def minCameraCover(self, root: TreeNode) -> int:
#选择后序遍历 迭代
res=0
stacker = [root]
while stacker:
noder = stacker.pop()
if noder: #左右中
stacker.append(noder)
stacker.append(None)
if noder.right: stacker.append(noder.right)
if noder.left: stacker.append(noder.left)
else:
noder = stacker.pop()
if noder.left: leftval=noder.left.val
else:leftval=2
if noder.right: rightval=noder.right.val
else:rightval=2
if leftval==2 and rightval==2:noder.val=0
elif leftval==0 or rightval==0:
res+=1
noder.val=1
elif leftval==1 or rightval==1:noder.val=2
if not noder.val:res+=1
return res
7)总结
贪心的题,总有些小心思在里面,主要你能想到那个小心思,其实都比较好解决。
贪心算法告一段落了,明天就开始看动态规划了,传说中的dp()数组或列表。