Gemini永久会员 # LintCode 3893 · 二叉树中得到结果所需的最少翻转次数 - Java实现
·
这个问题要求我们计算在二叉树中通过翻转节点值(0变1,1变0)使得根节点到所有叶子节点的路径值都相同的所需最少翻转次数。
方法思路1. 深度优先搜索(DFS):我们需要遍历所有从根到叶子的路径,计算每条路径的翻转次数。
- 比较路径:对于每条路径,我们需要记录翻转次数,并最终找到所有路径中的最大公约数(GCD)或最小公倍数(LCM)来确定最少需要的翻转次数。
. 动态规划:更高效的方法是使用后序遍历,在每个节点计算使其左右子树路径一致所需的最小翻转次数。
解决代码
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
public class Solution {
private int minFlips = Integer.MAX_VALUE;
public int minFlipsToUniform(TreeNode root) {
if (root == null) return 0;
dfs(root);
return minFlips;
private int[] dfs(TreeNode node) {
if (node == null) {
return new int[]{0, 0}; // {flips to 0, flips to 1}
}
int[] left = dfs(node.left);
int[] right = dfs(node.right);
int[] res = new int[2];
// Current node is 0 int flipLeft0 = left[0] + (node.left != null && node.left.val != 0 ? 1 : 0);
int flipRight0 = right[0] + (node.right != null && node.right.val != 0 ? 1 : 0);
res[0] = flipLeft0 + flipRight0;
// Current node is 1
int flipLeft1 = left[1] + (node.left != null && node.left.val != 1 ? 1 : 0);
int flipRight1 = right[1] + (node.right != null && node.right.val != 1 ? 1 : 0);
res[1] = flipLeft1 + flipRight1;
// Update global min flips
minFlips = Math.min(minFlips, Math.min(res[0], res[1]));
// For parent nodes, we need to choose one path (either all 0 or all 1)
// So we return the minimal f for both options int[] result = new int[2];
result[0] = res[0]; // if parent chooses 0, we take the 0 pathlips
result[1] = res]; // if parent chooses 1, we take the 1 path flips
// But actually need to children consistent
we minimal between making left and consistent part need
at each node, choose to make left and right same as current node
// Revised approach:
For current node to be 0:
// - left child must be 0 (flip if not)
// - right child must be 0 (flip if not)
int totalFlip0 = (node.left != null ? (node.left.val == 0 ? left[0] : left1] + 1) : 0)
node.right != null ? (node.right.val == 0 ? right[0] : right[1] + 1) : 0);
// For current node to be 1:
// - left child must be1 (flip if not)
// - right child must be 1 (flip if not)
int totalFlip1 = (node.left != null ? (node.left.val == 1 ? left[1] : left[0] + 1) : 0)
+ (node.right != null ? (node.right.val == 1 ? right[1] : right[0] + 1) : 0);
// The current node can choose to be 0 or 1, so we return both possibilities
// But for the root, we'll take the minimal of the two
return new int[]{totalFlip0, totalFlip1};
}
// Alternative implementation that correctly computes the minimal flips
public int minFlipsToUniformCorrect(TreeNode root) {
int[] result = dfsCorrect(root);
return Math.min(result[0], result[1]);
}
private int[] dfsCorrect(TreeNode node) {
if (node == null) {
return new int[]{0, 0};
}
int[] left = dfsCorrect(node.left);
int[] right = dfsCorrect(node.right);
int[] res = new int[2];
// Option 1: make current node 0
// Then left and right must be 0
int flipLeftTo0 = (node.left != null ? (node.left.val == 0 ? left[0] : left[1] + 1) : 0);
int flipRightTo0 = (node.right != null ? (node.right.val == 0 ? right[0] : right[1] + 1) : 0);
res[0] = flipLeftTo0 + flipRightTo0;
// Option 2: make current node 1
// Then left and right must be 1
int flipLeftTo1 = (node.left != null ? (node.left.val == 1 ? left[1] : left[0] + 1) : 0);
int flipRightTo1 = (node.right != null ? (node.right.val == 1 ? right[1] : right[0] + 1) : 0);
res[1] = flipLeftTo1 + flipRightTo1;
return res;
}
}
代码解释
- TreeNode类:定义了二叉树节点的结构。
- minFlipsToUniform方法:主方法,调用DFS遍历树并返回最少翻转次数。
- dfs方法:递归计算每个节点使其子树路径一致所需的最小翻转次数。对于每个节点,计算将其值设为0或1时的翻转次数,并返回这两种情况的值供父节点使用。
- minFlipsToUniformCorrect方法:更正确的实现,通过后序遍历计算每个节点使其子树路径一致的最小翻转次数,最终返回根节点选择0或1的最小值。
- dfsCorrect方法:修正后的DFS实现,确保在每个节点正确计算使其左右子树路径一致的最小翻转次数。
这个问题的关键在于后序遍历和动态规划的结合,确保在每个节点做出局部最优选择,从而得到全局最优解。
更多推荐



所有评论(0)