738.单调递增的数字
思路
这一道题使用的贪心思路是:
- 首先将数字变成字符串
- 从后往前遍历每个位数的数字
- 一旦出现
strNum[i - 1] > strNum[i]
的情况(非单调递增),让strNum[i - 1]
减一,strNum[i] = 9
- 局部最优会引向全局最优
代码
卡哥的代码使用了flag
来记录需要更换成9的digit的位置,这样能省得在for loop里面直接改。
class Solution:
def monotoneIncreasingDigits(self, n: int) -> int:
strN = str(n)
flag = len(strN)
for i in range(len(strN) - 1, 0, -1):
if int(strN[i-1]) > int(strN[i]):
flag = i
strN = strN[:i-1] + str(int(strN[i-1]) - 1) + strN[i:]
for i in range(flag, len(strN)):
strN = strN[:i] + '9' + strN[i+1:]
return int(strN)
复杂度分析
- 时间复杂度:
O(n)
,n
为数字长度 - 空间复杂度:
O(n)
,需要一个字符串,转化为字符串操作更方便
968.监控二叉树
思路
这道题对节点的不同状态分为三种:
0 -> 无覆盖
1 -> 有摄像头
2 -> 有覆盖
通过对状态的推导和转移来确定该节点是否为摄像头节点。
具体的细节可以看
代码
我写的
# 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: Optional[TreeNode]) -> int:
res = 0
def dfs(cur):
nonlocal res
if not cur:
return 2
left = dfs(cur.left)
right = dfs(cur.right)
if left == 2 and right == 2:
return 0
if left == 0 or right == 0:
res += 1
return 1
if left == 1 or right == 1:
return 2
if dfs(root) == 0:
res += 1
return res
卡哥的注释代码
class Solution:
# Greedy Algo:
# 从下往上安装摄像头:跳过leaves这样安装数量最少,局部最优 -> 全局最优
# 先给leaves的父节点安装,然后每隔两层节点安装一个摄像头,直到Head
# 0: 该节点未覆盖
# 1: 该节点有摄像头
# 2: 该节点有覆盖
def minCameraCover(self, root: TreeNode) -> int:
# 定义递归函数
result = [0] # 用于记录摄像头的安装数量
if self.traversal(root, result) == 0:
result[0] += 1
return result[0]
def traversal(self, cur: TreeNode, result: List[int]) -> int:
if not cur:
return 2
left = self.traversal(cur.left, result)
right = self.traversal(cur.right, result)
# 情况1: 左右节点都有覆盖
if left == 2 and right == 2:
return 0
# 情况2:
# left == 0 && right == 0 左右节点无覆盖
# left == 1 && right == 0 左节点有摄像头,右节点无覆盖
# left == 0 && right == 1 左节点无覆盖,右节点有摄像头
# left == 0 && right == 2 左节点无覆盖,右节点覆盖
# left == 2 && right == 0 左节点覆盖,右节点无覆盖
if left == 0 or right == 0:
result[0] += 1
return 1
# 情况3:
# left == 1 && right == 2 左节点有摄像头,右节点有覆盖
# left == 2 && right == 1 左节点有覆盖,右节点有摄像头
# left == 1 && right == 1 左右节点都有摄像头
if left == 1 or right == 1:
return 2
总结
套用卡哥知识星球其中一位成员:海螺人的总结图