当且仅当每个相邻位数上的数字 x
和 y
满足 x <= y
时,我们称这个整数是单调递增的。
给定一个整数 n
,返回 小于或等于 n
的最大数字,且数字呈 单调递增 。
思路:找到一个尽可能大的,不比给定整数小的整数。首先,如果该数本身便是单调递增,那么返回本数就可以。如果不是,则自然地,将非递增的位置减一,然后为了让数字最大,后面的全部变为9。为实现这一点,应该从后往前遍历。
Python:
class Solution:
def monotoneIncreasingDigits(self, n: int) -> int:
# 将整数转换为字符串列表
strNum = list(str(n))
# 从右往左遍历字符串
for i in range(len(strNum) - 1, 0, -1):
# 如果当前字符比后面一个字符小,说明需要修改前一个字符
if strNum[i - 1] > strNum[i]:
strNum[i - 1] = str(int(strNum[i - 1]) - 1) # 将前一个字符减1
# 将修改位置后面的字符都设置为9
for j in range(i, len(strNum)):
strNum[j] = '9'
# 将列表转换为字符串,并将字符串转换为整数并返回
return int(''.join(strNum))
给定一个二叉树,我们在树的节点上安装摄像头。
节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。
计算监控树的所有节点所需的最小摄像头数量。
思路:叶子结点的父节点放摄像头,所有叶子结点都监控到(树越深结点越多,这样做最省)。然后因为摄像头的父结点也能监控到,所以隔一层装一层摄像头(因为可能有上一层的叶子节点,所以不可以隔两层)。因为是从深层往前层,所以用后序遍历。树的结点可以分为三个状态,一个时放置摄像头,一个是被摄像头所覆盖,一个是没有摄像头且没有被覆盖。首先判断是否应该放摄像头,如果左右节点有一个没有被覆盖,那么就需要放摄像头。然后判断是否被覆盖,如果叶子节点有摄像头,那么代表被覆盖。否则就是没有被覆盖。
class Solution:
# Greedy Algo:
# 从下往上安装摄像头:跳过leaves这样安装数量最少,局部最优 -> 全局最优
# 先给leaves的父节点安装,然后每隔两层节点安装一个摄像头,直到Head
# 0: 该节点未覆盖
# 1: 该节点有摄像头
# 2: 该节点有覆盖
def minCameraCover(self, root: TreeNode) -> int:
# 定义递归函数
ans = [0] # 用于记录摄像头的安装数量
if self.traversal(root, ans) == 0: # 判断根节点是否被覆盖,如果没有被覆盖就要额外一个摄像头
ans[0] += 1
return ans[0]
def traversal(self, cur: TreeNode, ans: 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:
ans[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