|
67 | 67 |
|
68 | 68 | <!-- 这里可写通用的实现逻辑 -->
|
69 | 69 |
|
| 70 | +**方法一:树形 DP + 分情况讨论** |
| 71 | + |
| 72 | +我们定义一个函数 $dfs(root)$,它的返回值是一个长度为 $2$ 的数组,其中第一个表示将 $root$ 节点的值变成 `false` 所需要的最少翻转次数,第二个表示将 $root$ 节点的值变成 `true` 所需要的最少翻转次数。那么答案为 $dfs(root)[result]$。 |
| 73 | + |
| 74 | +函数 $dfs(root)$ 的实现如下: |
| 75 | + |
| 76 | +如果 $root$ 为空,那么返回 $[+\infty, +\infty]$。 |
| 77 | + |
| 78 | +否则,我们记 $root$ 的值为 $x$,左子树的返回值为 $l$,右子树的返回值为 $r$,然后分情况讨论: |
| 79 | + |
| 80 | +- 如果 $x \in \{0, 1\}$,那么返回 $[x, x \oplus 1]$。 |
| 81 | +- 如果 $x = 2$,即布尔运算符是 `OR`,为了使 $root$ 的值为 `false`,我们需要将左右子树的值都变成 `false`,因此返回值的第一个元素为 $l[0] + r[0]$;为了使 $root$ 的值为 `true`,我们需要将左右子树的值中至少有一个变成 `true`,因此返回值的第二个元素为 $\min(l[0] + r[1], l[1] + r[0], l[1] + r[1])$。 |
| 82 | +- 如果 $x = 3$,即布尔运算符是 `AND`,为了使 $root$ 的值为 `false`,我们需要将左右子树的值中至少有一个变成 `false`,因此返回值的第一个元素为 $\min(l[0] + r[0], l[0] + r[1], l[1] + r[0])$;为了使 $root$ 的值为 `true`,我们需要将左右子树的值都变成 `true`,因此返回值的第二个元素为 $l[1] + r[1]$。 |
| 83 | +- 如果 $x = 4$,即布尔运算符是 `XOR`,为了使 $root$ 的值为 `false`,我们需要将左右子树的值同为 `false` 或同为 `true`,因此返回值的第一个元素为 $\min(l[0] + r[0], l[1] + r[1])$;为了使 $root$ 的值为 `true`,我们需要将左右子树的值不同,因此返回值的第二个元素为 $\min(l[0] + r[1], l[1] + r[0])$。 |
| 84 | +- 如果 $x = 5$,即布尔运算符是 `NOT`,为了使 $root$ 的值为 `false`,我们需要将左右子树的值中至少有一个变成 `true`,因此返回值的第一个元素为 $\min(l[1], r[1])$;为了使 $root$ 的值为 `true`,我们需要将左右子树的值中至少有一个变成 `false`,因此返回值的第二个元素为 $\min(l[0], r[0])$。 |
| 85 | + |
| 86 | +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是二叉树的节点数。 |
| 87 | + |
70 | 88 | <!-- tabs:start -->
|
71 | 89 |
|
72 | 90 | ### **Python3**
|
73 | 91 |
|
74 | 92 | <!-- 这里可写当前语言的特殊实现逻辑 -->
|
75 | 93 |
|
76 | 94 | ```python
|
77 |
| - |
| 95 | +# Definition for a binary tree node. |
| 96 | +# class TreeNode: |
| 97 | +# def __init__(self, val=0, left=None, right=None): |
| 98 | +# self.val = val |
| 99 | +# self.left = left |
| 100 | +# self.right = right |
| 101 | +class Solution: |
| 102 | + def minimumFlips(self, root: Optional[TreeNode], result: bool) -> int: |
| 103 | + def dfs(root: Optional[TreeNode]) -> (int, int): |
| 104 | + if root is None: |
| 105 | + return inf, inf |
| 106 | + x = root.val |
| 107 | + if x in (0, 1): |
| 108 | + return x, x ^ 1 |
| 109 | + l, r = dfs(root.left), dfs(root.right) |
| 110 | + if x == 2: |
| 111 | + return l[0] + r[0], min(l[0] + r[1], l[1] + r[0], l[1] + r[1]) |
| 112 | + if x == 3: |
| 113 | + return min(l[0] + r[0], l[0] + r[1], l[1] + r[0]), l[1] + r[1] |
| 114 | + if x == 4: |
| 115 | + return min(l[0] + r[0], l[1] + r[1]), min(l[0] + r[1], l[1] + r[0]) |
| 116 | + return min(l[1], r[1]), min(l[0], r[0]) |
| 117 | + |
| 118 | + return dfs(root)[int(result)] |
78 | 119 | ```
|
79 | 120 |
|
80 | 121 | ### **Java**
|
81 | 122 |
|
82 | 123 | <!-- 这里可写当前语言的特殊实现逻辑 -->
|
83 | 124 |
|
84 | 125 | ```java
|
| 126 | +/** |
| 127 | + * Definition for a binary tree node. |
| 128 | + * public class TreeNode { |
| 129 | + * int val; |
| 130 | + * TreeNode left; |
| 131 | + * TreeNode right; |
| 132 | + * TreeNode() {} |
| 133 | + * TreeNode(int val) { this.val = val; } |
| 134 | + * TreeNode(int val, TreeNode left, TreeNode right) { |
| 135 | + * this.val = val; |
| 136 | + * this.left = left; |
| 137 | + * this.right = right; |
| 138 | + * } |
| 139 | + * } |
| 140 | + */ |
| 141 | +class Solution { |
| 142 | + public int minimumFlips(TreeNode root, boolean result) { |
| 143 | + return dfs(root)[result ? 1 : 0]; |
| 144 | + } |
| 145 | + |
| 146 | + private int[] dfs(TreeNode root) { |
| 147 | + if (root == null) { |
| 148 | + return new int[] {1 << 30, 1 << 30}; |
| 149 | + } |
| 150 | + int x = root.val; |
| 151 | + if (x < 2) { |
| 152 | + return new int[] {x, x ^ 1}; |
| 153 | + } |
| 154 | + var l = dfs(root.left); |
| 155 | + var r = dfs(root.right); |
| 156 | + int a = 0, b = 0; |
| 157 | + if (x == 2) { |
| 158 | + a = l[0] + r[0]; |
| 159 | + b = Math.min(l[0] + r[1], Math.min(l[1] + r[0], l[1] + r[1])); |
| 160 | + } else if (x == 3) { |
| 161 | + a = Math.min(l[0] + r[0], Math.min(l[0] + r[1], l[1] + r[0])); |
| 162 | + b = l[1] + r[1]; |
| 163 | + } else if (x == 4) { |
| 164 | + a = Math.min(l[0] + r[0], l[1] + r[1]); |
| 165 | + b = Math.min(l[0] + r[1], l[1] + r[0]); |
| 166 | + } else { |
| 167 | + a = Math.min(l[1], r[1]); |
| 168 | + b = Math.min(l[0], r[0]); |
| 169 | + } |
| 170 | + return new int[] {a, b}; |
| 171 | + } |
| 172 | +} |
| 173 | +``` |
85 | 174 |
|
| 175 | +### **C++** |
| 176 | + |
| 177 | +```cpp |
| 178 | +/** |
| 179 | + * Definition for a binary tree node. |
| 180 | + * struct TreeNode { |
| 181 | + * int val; |
| 182 | + * TreeNode *left; |
| 183 | + * TreeNode *right; |
| 184 | + * TreeNode() : val(0), left(nullptr), right(nullptr) {} |
| 185 | + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} |
| 186 | + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} |
| 187 | + * }; |
| 188 | + */ |
| 189 | +class Solution { |
| 190 | +public: |
| 191 | + int minimumFlips(TreeNode* root, bool result) { |
| 192 | + function<pair<int, int>(TreeNode*)> dfs = [&](TreeNode* root) -> pair<int, int> { |
| 193 | + if (!root) { |
| 194 | + return {1 << 30, 1 << 30}; |
| 195 | + } |
| 196 | + int x = root->val; |
| 197 | + if (x < 2) { |
| 198 | + return {x, x ^ 1}; |
| 199 | + } |
| 200 | + auto [l0, l1] = dfs(root->left); |
| 201 | + auto [r0, r1] = dfs(root->right); |
| 202 | + int a = 0, b = 0; |
| 203 | + if (x == 2) { |
| 204 | + a = l0 + r0; |
| 205 | + b = min({l0 + r1, l1 + r0, l1 + r1}); |
| 206 | + } else if (x == 3) { |
| 207 | + a = min({l0 + r0, l0 + r1, l1 + r0}); |
| 208 | + b = l1 + r1; |
| 209 | + } else if (x == 4) { |
| 210 | + a = min(l0 + r0, l1 + r1); |
| 211 | + b = min(l0 + r1, l1 + r0); |
| 212 | + } else { |
| 213 | + a = min(l1, r1); |
| 214 | + b = min(l0, r0); |
| 215 | + } |
| 216 | + return {a, b}; |
| 217 | + }; |
| 218 | + auto [a, b] = dfs(root); |
| 219 | + return result ? b : a; |
| 220 | + } |
| 221 | +}; |
| 222 | +``` |
| 223 | +
|
| 224 | +### **Go** |
| 225 | +
|
| 226 | +```go |
| 227 | +/** |
| 228 | + * Definition for a binary tree node. |
| 229 | + * type TreeNode struct { |
| 230 | + * Val int |
| 231 | + * Left *TreeNode |
| 232 | + * Right *TreeNode |
| 233 | + * } |
| 234 | + */ |
| 235 | +func minimumFlips(root *TreeNode, result bool) int { |
| 236 | + var dfs func(*TreeNode) (int, int) |
| 237 | + dfs = func(root *TreeNode) (int, int) { |
| 238 | + if root == nil { |
| 239 | + return 1 << 30, 1 << 30 |
| 240 | + } |
| 241 | + x := root.Val |
| 242 | + if x < 2 { |
| 243 | + return x, x ^ 1 |
| 244 | + } |
| 245 | + l0, l1 := dfs(root.Left) |
| 246 | + r0, r1 := dfs(root.Right) |
| 247 | + var a, b int |
| 248 | + if x == 2 { |
| 249 | + a = l0 + r0 |
| 250 | + b = min(l0+r1, min(l1+r0, l1+r1)) |
| 251 | + } else if x == 3 { |
| 252 | + a = min(l0+r0, min(l0+r1, l1+r0)) |
| 253 | + b = l1 + r1 |
| 254 | + } else if x == 4 { |
| 255 | + a = min(l0+r0, l1+r1) |
| 256 | + b = min(l0+r1, l1+r0) |
| 257 | + } else { |
| 258 | + a = min(l1, r1) |
| 259 | + b = min(l0, r0) |
| 260 | + } |
| 261 | + return a, b |
| 262 | + } |
| 263 | + a, b := dfs(root) |
| 264 | + if result { |
| 265 | + return b |
| 266 | + } |
| 267 | + return a |
| 268 | +} |
| 269 | +
|
| 270 | +func min(a, b int) int { |
| 271 | + if a < b { |
| 272 | + return a |
| 273 | + } |
| 274 | + return b |
| 275 | +} |
86 | 276 | ```
|
87 | 277 |
|
88 | 278 | ### **TypeScript**
|
89 | 279 |
|
90 | 280 | ```ts
|
91 |
| - |
| 281 | +/** |
| 282 | + * Definition for a binary tree node. |
| 283 | + * class TreeNode { |
| 284 | + * val: number |
| 285 | + * left: TreeNode | null |
| 286 | + * right: TreeNode | null |
| 287 | + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { |
| 288 | + * this.val = (val===undefined ? 0 : val) |
| 289 | + * this.left = (left===undefined ? null : left) |
| 290 | + * this.right = (right===undefined ? null : right) |
| 291 | + * } |
| 292 | + * } |
| 293 | + */ |
| 294 | + |
| 295 | +function minimumFlips(root: TreeNode | null, result: boolean): number { |
| 296 | + const dfs = (root: TreeNode | null): [number, number] => { |
| 297 | + if (!root) { |
| 298 | + return [1 << 30, 1 << 30]; |
| 299 | + } |
| 300 | + const x = root.val; |
| 301 | + if (x < 2) { |
| 302 | + return [x, x ^ 1]; |
| 303 | + } |
| 304 | + const [l0, l1] = dfs(root.left); |
| 305 | + const [r0, r1] = dfs(root.right); |
| 306 | + if (x === 2) { |
| 307 | + return [l0 + r0, Math.min(l0 + r1, l1 + r0, l1 + r1)]; |
| 308 | + } |
| 309 | + if (x === 3) { |
| 310 | + return [Math.min(l0 + r0, l0 + r1, l1 + r0), l1 + r1]; |
| 311 | + } |
| 312 | + if (x === 4) { |
| 313 | + return [Math.min(l0 + r0, l1 + r1), Math.min(l0 + r1, l1 + r0)]; |
| 314 | + } |
| 315 | + return [Math.min(l1, r1), Math.min(l0, r0)]; |
| 316 | + }; |
| 317 | + return dfs(root)[result ? 1 : 0]; |
| 318 | +} |
92 | 319 | ```
|
93 | 320 |
|
94 | 321 | ### **...**
|
|
0 commit comments