力扣刷题-python-贪心算法(完结)-2

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()数组或列表。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值