mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-08 00:43:04 +08:00
Merge pull request #2118 from jianghongcheng/master
Update 0968.监控二叉树.md
This commit is contained in:
@ -287,17 +287,70 @@ public:
|
||||
```
|
||||
|
||||
### Python
|
||||
|
||||
递归
|
||||
```python
|
||||
class Solution: # 动态规划
|
||||
class Solution:
|
||||
def uniquePaths(self, m: int, n: int) -> int:
|
||||
dp = [[1 for i in range(n)] for j in range(m)]
|
||||
if m == 1 or n == 1:
|
||||
return 1
|
||||
return self.uniquePaths(m - 1, n) + self.uniquePaths(m, n - 1)
|
||||
|
||||
```
|
||||
动态规划(版本一)
|
||||
```python
|
||||
class Solution:
|
||||
def uniquePaths(self, m: int, n: int) -> int:
|
||||
# 创建一个二维列表用于存储唯一路径数
|
||||
dp = [[0] * n for _ in range(m)]
|
||||
|
||||
# 设置第一行和第一列的基本情况
|
||||
for i in range(m):
|
||||
dp[i][0] = 1
|
||||
for j in range(n):
|
||||
dp[0][j] = 1
|
||||
|
||||
# 计算每个单元格的唯一路径数
|
||||
for i in range(1, m):
|
||||
for j in range(1, n):
|
||||
dp[i][j] = dp[i][j - 1] + dp[i - 1][j]
|
||||
dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
|
||||
|
||||
# 返回右下角单元格的唯一路径数
|
||||
return dp[m - 1][n - 1]
|
||||
```
|
||||
|
||||
```
|
||||
动态规划(版本二)
|
||||
```python
|
||||
class Solution:
|
||||
def uniquePaths(self, m: int, n: int) -> int:
|
||||
# 创建一个一维列表用于存储每列的唯一路径数
|
||||
dp = [1] * n
|
||||
|
||||
# 计算每个单元格的唯一路径数
|
||||
for j in range(1, m):
|
||||
for i in range(1, n):
|
||||
dp[i] += dp[i - 1]
|
||||
|
||||
# 返回右下角单元格的唯一路径数
|
||||
return dp[n - 1]
|
||||
```
|
||||
数论
|
||||
```python
|
||||
class Solution:
|
||||
def uniquePaths(self, m: int, n: int) -> int:
|
||||
numerator = 1 # 分子
|
||||
denominator = m - 1 # 分母
|
||||
count = m - 1 # 计数器,表示剩余需要计算的乘积项个数
|
||||
t = m + n - 2 # 初始乘积项
|
||||
while count > 0:
|
||||
numerator *= t # 计算乘积项的分子部分
|
||||
t -= 1 # 递减乘积项
|
||||
while denominator != 0 and numerator % denominator == 0:
|
||||
numerator //= denominator # 约简分子
|
||||
denominator -= 1 # 递减分母
|
||||
count -= 1 # 计数器减1,继续下一项的计算
|
||||
return numerator # 返回最终的唯一路径数
|
||||
|
||||
```
|
||||
### Go
|
||||
|
||||
```Go
|
||||
|
@ -271,69 +271,130 @@ class Solution {
|
||||
|
||||
|
||||
### Python
|
||||
|
||||
动态规划(版本一)
|
||||
```python
|
||||
class Solution:
|
||||
def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
|
||||
# 构造一个DP table
|
||||
row = len(obstacleGrid)
|
||||
col = len(obstacleGrid[0])
|
||||
dp = [[0 for _ in range(col)] for _ in range(row)]
|
||||
dp[0][0] = 0 if obstacleGrid[0][0] == 1 else 1
|
||||
if dp[0][0] == 0:
|
||||
return 0 # 如果第一个格子就是障碍,return 0
|
||||
# 第一行
|
||||
for i in range(1, col):
|
||||
if obstacleGrid[0][i] == 1:
|
||||
# 遇到障碍物时,直接退出循环,后面默认都是0
|
||||
def uniquePathsWithObstacles(self, obstacleGrid):
|
||||
m = len(obstacleGrid)
|
||||
n = len(obstacleGrid[0])
|
||||
if obstacleGrid[m - 1][n - 1] == 1 or obstacleGrid[0][0] == 1:
|
||||
return 0
|
||||
dp = [[0] * n for _ in range(m)]
|
||||
for i in range(m):
|
||||
if obstacleGrid[i][0] == 0: # 遇到障碍物时,直接退出循环,后面默认都是0
|
||||
dp[i][0] = 1
|
||||
else:
|
||||
break
|
||||
dp[0][i] = 1
|
||||
|
||||
# 第一列
|
||||
for i in range(1, row):
|
||||
if obstacleGrid[i][0] == 1:
|
||||
# 遇到障碍物时,直接退出循环,后面默认都是0
|
||||
for j in range(n):
|
||||
if obstacleGrid[0][j] == 0:
|
||||
dp[0][j] = 1
|
||||
else:
|
||||
break
|
||||
dp[i][0] = 1
|
||||
# print(dp)
|
||||
for i in range(1, m):
|
||||
for j in range(1, n):
|
||||
if obstacleGrid[i][j] == 1:
|
||||
continue
|
||||
dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
|
||||
return dp[m - 1][n - 1]
|
||||
|
||||
for i in range(1, row):
|
||||
for j in range(1, col):
|
||||
if obstacleGrid[i][j] == 0:
|
||||
dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
|
||||
return dp[-1][-1]
|
||||
```
|
||||
动态规划(版本二)
|
||||
```python
|
||||
class Solution:
|
||||
def uniquePathsWithObstacles(self, obstacleGrid):
|
||||
m = len(obstacleGrid) # 网格的行数
|
||||
n = len(obstacleGrid[0]) # 网格的列数
|
||||
|
||||
if obstacleGrid[m - 1][n - 1] == 1 or obstacleGrid[0][0] == 1:
|
||||
# 如果起点或终点有障碍物,直接返回0
|
||||
return 0
|
||||
|
||||
dp = [[0] * n for _ in range(m)] # 创建一个二维列表用于存储路径数
|
||||
|
||||
# 设置起点的路径数为1
|
||||
dp[0][0] = 1 if obstacleGrid[0][0] == 0 else 0
|
||||
|
||||
# 计算第一列的路径数
|
||||
for i in range(1, m):
|
||||
if obstacleGrid[i][0] == 0:
|
||||
dp[i][0] = dp[i - 1][0]
|
||||
|
||||
# 计算第一行的路径数
|
||||
for j in range(1, n):
|
||||
if obstacleGrid[0][j] == 0:
|
||||
dp[0][j] = dp[0][j - 1]
|
||||
|
||||
# 计算其他位置的路径数
|
||||
for i in range(1, m):
|
||||
for j in range(1, n):
|
||||
if obstacleGrid[i][j] == 1:
|
||||
continue
|
||||
dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
|
||||
|
||||
return dp[m - 1][n - 1] # 返回终点的路径数
|
||||
|
||||
|
||||
```
|
||||
动态规划(版本三)
|
||||
|
||||
```python
|
||||
class Solution:
|
||||
"""
|
||||
使用一维dp数组
|
||||
"""
|
||||
def uniquePathsWithObstacles(self, obstacleGrid):
|
||||
if obstacleGrid[0][0] == 1:
|
||||
return 0
|
||||
|
||||
dp = [0] * len(obstacleGrid[0]) # 创建一个一维列表用于存储路径数
|
||||
|
||||
# 初始化第一行的路径数
|
||||
for j in range(len(dp)):
|
||||
if obstacleGrid[0][j] == 1:
|
||||
dp[j] = 0
|
||||
elif j == 0:
|
||||
dp[j] = 1
|
||||
else:
|
||||
dp[j] = dp[j - 1]
|
||||
|
||||
def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
|
||||
# 计算其他行的路径数
|
||||
for i in range(1, len(obstacleGrid)):
|
||||
for j in range(len(dp)):
|
||||
if obstacleGrid[i][j] == 1:
|
||||
dp[j] = 0
|
||||
elif j != 0:
|
||||
dp[j] = dp[j] + dp[j - 1]
|
||||
|
||||
return dp[-1] # 返回最后一个元素,即终点的路径数
|
||||
|
||||
```
|
||||
动态规划(版本四)
|
||||
|
||||
```python
|
||||
class Solution:
|
||||
def uniquePathsWithObstacles(self, obstacleGrid):
|
||||
if obstacleGrid[0][0] == 1:
|
||||
return 0
|
||||
|
||||
m, n = len(obstacleGrid), len(obstacleGrid[0])
|
||||
|
||||
# 初始化dp数组
|
||||
# 该数组缓存当前行
|
||||
curr = [0] * n
|
||||
|
||||
dp = [0] * n # 创建一个一维列表用于存储路径数
|
||||
|
||||
# 初始化第一行的路径数
|
||||
for j in range(n):
|
||||
if obstacleGrid[0][j] == 1:
|
||||
break
|
||||
curr[j] = 1
|
||||
dp[j] = 1
|
||||
|
||||
for i in range(1, m): # 从第二行开始
|
||||
for j in range(n): # 从第一列开始,因为第一列可能有障碍物
|
||||
# 有障碍物处无法通行,状态就设成0
|
||||
# 计算其他行的路径数
|
||||
for i in range(1, m):
|
||||
if obstacleGrid[i][0] == 1:
|
||||
dp[0] = 0
|
||||
for j in range(1, n):
|
||||
if obstacleGrid[i][j] == 1:
|
||||
curr[j] = 0
|
||||
elif j > 0:
|
||||
# 等价于
|
||||
# dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
|
||||
curr[j] = curr[j] + curr[j - 1]
|
||||
# 隐含的状态更新
|
||||
# dp[i][0] = dp[i - 1][0]
|
||||
dp[j] = 0
|
||||
else:
|
||||
dp[j] += dp[j - 1]
|
||||
|
||||
return dp[-1] # 返回最后一个元素,即终点的路径数
|
||||
|
||||
return curr[n - 1]
|
||||
```
|
||||
|
||||
|
||||
|
@ -251,32 +251,66 @@ class Solution {
|
||||
```
|
||||
|
||||
### Python
|
||||
|
||||
动态规划(版本一)
|
||||
```python
|
||||
# 空间复杂度为O(n)版本
|
||||
class Solution:
|
||||
def climbStairs(self, n: int) -> int:
|
||||
# dp[i] 为第 i 阶楼梯有多少种方法爬到楼顶
|
||||
dp = [0]*(n+1)
|
||||
dp[0] = 1
|
||||
if n <= 1:
|
||||
return n
|
||||
|
||||
dp = [0] * (n + 1)
|
||||
dp[1] = 1
|
||||
for i in range(2, n+1):
|
||||
dp[i] = dp[i-1] + dp[i-2]
|
||||
dp[2] = 2
|
||||
|
||||
for i in range(3, n + 1):
|
||||
dp[i] = dp[i - 1] + dp[i - 2]
|
||||
|
||||
return dp[n]
|
||||
|
||||
```
|
||||
动态规划(版本二)
|
||||
```python
|
||||
|
||||
# 空间复杂度为O(3)版本
|
||||
class Solution:
|
||||
def climbStairs(self, n: int) -> int:
|
||||
if n <= 1:
|
||||
return n
|
||||
|
||||
dp = [0] * 3
|
||||
dp[1] = 1
|
||||
dp[2] = 2
|
||||
|
||||
for i in range(3, n + 1):
|
||||
total = dp[1] + dp[2]
|
||||
dp[1] = dp[2]
|
||||
dp[2] = total
|
||||
|
||||
return dp[2]
|
||||
|
||||
```
|
||||
动态规划(版本三)
|
||||
```python
|
||||
|
||||
# 空间复杂度为O(1)版本
|
||||
class Solution:
|
||||
def climbStairs(self, n: int) -> int:
|
||||
dp = [0]*(n+1)
|
||||
dp[0] = 1
|
||||
dp[1] = 1
|
||||
for i in range(2,n+1):
|
||||
tmp = dp[0] + dp[1]
|
||||
dp[0] = dp[1]
|
||||
dp[1] = tmp
|
||||
return dp[1]
|
||||
```
|
||||
if n <= 1:
|
||||
return n
|
||||
|
||||
prev1 = 1
|
||||
prev2 = 2
|
||||
|
||||
for i in range(3, n + 1):
|
||||
total = prev1 + prev2
|
||||
prev1 = prev2
|
||||
prev2 = total
|
||||
|
||||
return prev2
|
||||
|
||||
|
||||
```
|
||||
### Go
|
||||
```Go
|
||||
func climbStairs(n int) int {
|
||||
|
@ -197,12 +197,13 @@ class Solution {
|
||||
```python
|
||||
class Solution:
|
||||
def numTrees(self, n: int) -> int:
|
||||
dp = [0] * (n + 1)
|
||||
dp[0], dp[1] = 1, 1
|
||||
for i in range(2, n + 1):
|
||||
for j in range(1, i + 1):
|
||||
dp[i] += dp[j - 1] * dp[i - j]
|
||||
return dp[-1]
|
||||
dp = [0] * (n + 1) # 创建一个长度为n+1的数组,初始化为0
|
||||
dp[0] = 1 # 当n为0时,只有一种情况,即空树,所以dp[0] = 1
|
||||
for i in range(1, n + 1): # 遍历从1到n的每个数字
|
||||
for j in range(1, i + 1): # 对于每个数字i,计算以i为根节点的二叉搜索树的数量
|
||||
dp[i] += dp[j - 1] * dp[i - j] # 利用动态规划的思想,累加左子树和右子树的组合数量
|
||||
return dp[n] # 返回以1到n为节点的二叉搜索树的总数量
|
||||
|
||||
```
|
||||
|
||||
### Go
|
||||
|
@ -245,20 +245,68 @@ class Solution {
|
||||
```
|
||||
|
||||
### Python
|
||||
动态规划(版本一)
|
||||
```python
|
||||
class Solution:
|
||||
def integerBreak(self, n: int) -> int:
|
||||
dp = [0] * (n + 1)
|
||||
dp[2] = 1
|
||||
# 假设对正整数 i 拆分出的第一个正整数是 j(1 <= j < i),则有以下两种方案:
|
||||
# 1) 将 i 拆分成 j 和 i−j 的和,且 i−j 不再拆分成多个正整数,此时的乘积是 j * (i-j)
|
||||
# 2) 将 i 拆分成 j 和 i−j 的和,且 i−j 继续拆分成多个正整数,此时的乘积是 j * dp[i-j]
|
||||
def integerBreak(self, n):
|
||||
dp = [0] * (n + 1) # 创建一个大小为n+1的数组来存储计算结果
|
||||
dp[2] = 1 # 初始化dp[2]为1,因为当n=2时,只有一个切割方式1+1=2,乘积为1
|
||||
|
||||
# 从3开始计算,直到n
|
||||
for i in range(3, n + 1):
|
||||
# 假设对正整数 i 拆分出的第一个正整数是 j(1 <= j < i),则有以下两种方案:
|
||||
# 1) 将 i 拆分成 j 和 i−j 的和,且 i−j 不再拆分成多个正整数,此时的乘积是 j * (i-j)
|
||||
# 2) 将 i 拆分成 j 和 i−j 的和,且 i−j 继续拆分成多个正整数,此时的乘积是 j * dp[i-j]
|
||||
# 遍历所有可能的切割点
|
||||
for j in range(1, i // 2 + 1):
|
||||
dp[i] = max(dp[i], max(j * (i - j), j * dp[i - j]))
|
||||
return dp[n]
|
||||
```
|
||||
|
||||
# 计算切割点j和剩余部分(i-j)的乘积,并与之前的结果进行比较取较大值
|
||||
|
||||
dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j))
|
||||
|
||||
return dp[n] # 返回最终的计算结果
|
||||
|
||||
```
|
||||
动态规划(版本二)
|
||||
```python
|
||||
class Solution:
|
||||
def integerBreak(self, n):
|
||||
if n <= 3:
|
||||
return 1 * (n - 1) # 对于n小于等于3的情况,返回1 * (n - 1)
|
||||
|
||||
dp = [0] * (n + 1) # 创建一个大小为n+1的数组来存储最大乘积结果
|
||||
dp[1] = 1 # 当n等于1时,最大乘积为1
|
||||
dp[2] = 2 # 当n等于2时,最大乘积为2
|
||||
dp[3] = 3 # 当n等于3时,最大乘积为3
|
||||
|
||||
# 从4开始计算,直到n
|
||||
for i in range(4, n + 1):
|
||||
# 遍历所有可能的切割点
|
||||
for j in range(1, i // 2 + 1):
|
||||
# 计算切割点j和剩余部分(i - j)的乘积,并与之前的结果进行比较取较大值
|
||||
dp[i] = max(dp[i], dp[i - j] * dp[j])
|
||||
|
||||
return dp[n] # 返回整数拆分的最大乘积结果
|
||||
|
||||
```
|
||||
贪心
|
||||
```python
|
||||
class Solution:
|
||||
def integerBreak(self, n):
|
||||
if n == 2: # 当n等于2时,只有一种拆分方式:1+1=2,乘积为1
|
||||
return 1
|
||||
if n == 3: # 当n等于3时,只有一种拆分方式:1+1+1=3,乘积为1
|
||||
return 2
|
||||
if n == 4: # 当n等于4时,有两种拆分方式:2+2=4和1+1+1+1=4,乘积都为4
|
||||
return 4
|
||||
result = 1
|
||||
while n > 4:
|
||||
result *= 3 # 每次乘以3,因为3的乘积比其他数字更大
|
||||
n -= 3 # 每次减去3
|
||||
result *= n # 将剩余的n乘以最后的结果
|
||||
return result
|
||||
|
||||
```
|
||||
### Go
|
||||
```go
|
||||
func integerBreak(n int) int {
|
||||
|
@ -203,18 +203,9 @@ class Solution {
|
||||
```
|
||||
|
||||
### Python
|
||||
动态规划(版本一)
|
||||
```python
|
||||
class Solution:
|
||||
def fib(self, n: int) -> int:
|
||||
if n < 2:
|
||||
return n
|
||||
a, b, c = 0, 1, 0
|
||||
for i in range(1, n):
|
||||
c = a + b
|
||||
a, b = b, c
|
||||
return c
|
||||
|
||||
# 动态规划 (注释版。无修饰)
|
||||
class Solution:
|
||||
def fib(self, n: int) -> int:
|
||||
|
||||
@ -238,7 +229,48 @@ class Solution:
|
||||
# 返回答案
|
||||
return dp[n]
|
||||
|
||||
# 递归实现
|
||||
```
|
||||
动态规划(版本二)
|
||||
```python
|
||||
|
||||
class Solution:
|
||||
def fib(self, n: int) -> int:
|
||||
if n <= 1:
|
||||
return n
|
||||
|
||||
dp = [0, 1]
|
||||
|
||||
for i in range(2, n + 1):
|
||||
total = dp[0] + dp[1]
|
||||
dp[0] = dp[1]
|
||||
dp[1] = total
|
||||
|
||||
return dp[1]
|
||||
|
||||
|
||||
```
|
||||
动态规划(版本三)
|
||||
```python
|
||||
class Solution:
|
||||
def fib(self, n: int) -> int:
|
||||
if n <= 1:
|
||||
return n
|
||||
|
||||
prev1, prev2 = 0, 1
|
||||
|
||||
for _ in range(2, n + 1):
|
||||
curr = prev1 + prev2
|
||||
prev1, prev2 = prev2, curr
|
||||
|
||||
return prev2
|
||||
|
||||
|
||||
|
||||
|
||||
```
|
||||
递归(版本一)
|
||||
```python
|
||||
|
||||
class Solution:
|
||||
def fib(self, n: int) -> int:
|
||||
if n < 2:
|
||||
|
@ -245,26 +245,42 @@ class Solution {
|
||||
```
|
||||
|
||||
### Python
|
||||
|
||||
动态规划(版本一)
|
||||
```python
|
||||
# 第一步不支付费用
|
||||
class Solution:
|
||||
def minCostClimbingStairs(self, cost: List[int]) -> int:
|
||||
n = len(cost)
|
||||
dp = [0]*(n+1) # 到达前两步费用为0
|
||||
for i in range(2, n+1):
|
||||
dp[i] = min(dp[i-1]+cost[i-1], dp[i-2]+cost[i-2])
|
||||
return dp[-1]
|
||||
```
|
||||
```python
|
||||
# 第一步支付费用
|
||||
|
||||
class Solution:
|
||||
def minCostClimbingStairs(self, cost: List[int]) -> int:
|
||||
dp = [0] * (len(cost) + 1)
|
||||
dp[0] = 0
|
||||
dp[1] = 0
|
||||
dp[0] = 0 # 初始值,表示从起点开始不需要花费体力
|
||||
dp[1] = 0 # 初始值,表示经过第一步不需要花费体力
|
||||
|
||||
for i in range(2, len(cost) + 1):
|
||||
dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i-2])
|
||||
return dp[len(cost)]
|
||||
# 在第i步,可以选择从前一步(i-1)花费体力到达当前步,或者从前两步(i-2)花费体力到达当前步
|
||||
# 选择其中花费体力较小的路径,加上当前步的花费,更新dp数组
|
||||
dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2])
|
||||
|
||||
return dp[len(cost)] # 返回到达楼顶的最小花费
|
||||
|
||||
```
|
||||
动态规划(版本二)
|
||||
|
||||
```python
|
||||
class Solution:
|
||||
def minCostClimbingStairs(self, cost: List[int]) -> int:
|
||||
dp0 = 0 # 初始值,表示从起点开始不需要花费体力
|
||||
dp1 = 0 # 初始值,表示经过第一步不需要花费体力
|
||||
|
||||
for i in range(2, len(cost) + 1):
|
||||
# 在第i步,可以选择从前一步(i-1)花费体力到达当前步,或者从前两步(i-2)花费体力到达当前步
|
||||
# 选择其中花费体力较小的路径,加上当前步的花费,得到当前步的最小花费
|
||||
dpi = min(dp1 + cost[i - 1], dp0 + cost[i - 2])
|
||||
|
||||
dp0 = dp1 # 更新dp0为前一步的值,即上一次循环中的dp1
|
||||
dp1 = dpi # 更新dp1为当前步的最小花费
|
||||
|
||||
return dp1 # 返回到达楼顶的最小花费
|
||||
|
||||
```
|
||||
|
||||
### Go
|
||||
|
@ -371,56 +371,104 @@ class Solution {
|
||||
|
||||
|
||||
### Python
|
||||
|
||||
贪心(版本一)
|
||||
```python
|
||||
class Solution:
|
||||
def minCameraCover(self, root: TreeNode) -> int:
|
||||
# Greedy Algo:
|
||||
# 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
|
||||
|
||||
result = 0
|
||||
# 从下往上遍历:后序(左右中)
|
||||
def traversal(curr: TreeNode) -> int:
|
||||
nonlocal result
|
||||
return result[0]
|
||||
|
||||
if not curr: return 2
|
||||
left = traversal(curr.left)
|
||||
right = traversal(curr.right)
|
||||
|
||||
def traversal(self, cur: TreeNode, result: List[int]) -> int:
|
||||
if not cur:
|
||||
return 2
|
||||
|
||||
# Case 1:
|
||||
# 左右节点都有覆盖
|
||||
if left == 2 and right == 2:
|
||||
return 0
|
||||
left = self.traversal(cur.left, result)
|
||||
right = self.traversal(cur.right, result)
|
||||
|
||||
# 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
|
||||
# 情况1: 左右节点都有覆盖
|
||||
if left == 2 and right == 2:
|
||||
return 0
|
||||
|
||||
# Case 3:
|
||||
# left == 1 && right == 2 左节点有摄像头,右节点有覆盖
|
||||
# left == 2 && right == 1 左节点有覆盖,右节点有摄像头
|
||||
# left == 1 && right == 1 左右节点都有摄像头
|
||||
elif left == 1 or right == 1:
|
||||
return 2
|
||||
# 情况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
|
||||
|
||||
if traversal(root) == 0:
|
||||
result += 1
|
||||
|
||||
return result
|
||||
```
|
||||
贪心(版本二)利用elif精简代码
|
||||
```python
|
||||
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 左节点覆盖,右节点无覆盖
|
||||
elif left == 0 or right == 0:
|
||||
result[0] += 1
|
||||
return 1
|
||||
|
||||
# 情况3:
|
||||
# left == 1 && right == 2 左节点有摄像头,右节点有覆盖
|
||||
# left == 2 && right == 1 左节点有覆盖,右节点有摄像头
|
||||
# left == 1 && right == 1 左右节点都有摄像头
|
||||
else:
|
||||
return 2
|
||||
|
||||
|
||||
|
||||
|
||||
```
|
||||
### Go
|
||||
|
||||
```go
|
||||
|
Reference in New Issue
Block a user