[ 线段树 ]LCP 52. 二叉搜索树染色

224 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第23天,点击查看活动详情


每日刷题 2021.04.23

题目

  • 欢迎各位勇者来到力扣城,本次试炼主题为「二叉搜索树染色」。
  • 每位勇士面前设有一个二叉搜索树的模型,模型的根节点为 root,树上的各个节点值均不重复。初始时,所有节点均为蓝色。现在按顺序对这棵二叉树进行若干次操作, ops[i] = [type, x, y] 表示第 i 次操作为:
    • type 等于 0 时,将节点值范围在 [x, y] 的节点均染蓝
    • type 等于 1 时,将节点值范围在 [x, y] 的节点均染红
  • 请返回完成所有染色后,该二叉树中红色节点的数量。
  • 注意:题目保证对于每个操作的 x、y 值定出现在二叉搜索树节点中

示例

  • 示例1 image.png
输入:root = [1,null,2,null,3,null,4,null,5], ops = [[1,2,4],[1,1,3],[0,3,5]]
输出:2

解释:
第 0 次操作,将值为 234 的节点染红;
第 1 次操作,将值为 123 的节点染红;
第 2 次操作,将值为 345 的节点染蓝;
因此,最终值为 12 的节点为红色节点,返回数量 2
  • 示例2
输入:root = [4,2,7,1,null,5,null,null,null,null,6]
ops = [[0,2,2],[1,1,5],[0,4,5],[1,5,7]]
输出:5

解释:
第 0 次操作,将值为 2 的节点染蓝;
第 1 次操作,将值为 1245 的节点染红;
第 2 次操作,将值为 45 的节点染蓝;
第 3 次操作,将值为 567 的节点染红;
因此,最终值为 12567 的节点为红色节点,返回数量 5

image.png

提示

  • 1 <= 二叉树节点数量 <= 10^5
  • 1 <= ops.length <= 10^5
  • ops[i].length == 3
  • ops[i][0] 仅为 0 or 1
  • 0 <= ops[i][1] <= ops[i][2] <= 10^9
  • 0 <= 节点值 <= 10^9

解题思路

拓展

  • 二叉搜索树:二叉搜索树(BST)又称二叉查找树或二叉排序树,如果左子树不为空,那么左子树的值一定小于根节点的值;如果右子树不为空,那么一定大于根节点的值。

实现思维

  • 根据题意分析:虽然题目中说的是二叉搜索树染色,但是其实可以直接将树上的元素遍历下来,成为一个数组,再进行操作。既然需要将其转换为数组,而这棵树又正好是二叉搜索树,因此可以使用中序遍历的方式,使得遍历树后形成的数组是有序的。
  • 获得有序的数组后,就需要考虑如何记录染色?
    • 将由树转换而来的数组,记为arr。遍历整个arr数组,使用map集合将其和下标进行绑定。
    • 再遍历输入样例中所给的ops数组,依次为每一个区间[x, y] 中的节点染色
    • 最后遍历每个节点所对应的颜色数组color,如果当前的颜色color[i] > 0,即:染为红色。那么就需要给最终的结果ans++

注意

  • 主要的思路转换:存在于将二叉搜索树的概念,以及转换为数组进行处理的思维。本题中的染色和二叉搜索树其实没有什么关系的,因此可以将其简化成熟悉的数组来进行处理。

AC代码

var getNumber = function(root, ops) {
  // 先将数转换成为数组
  let arr = [];
  function dfs(node) {
    if(node == null) return;
    if(node.left != null) dfs(node.left);
    arr.push(node.val);
    if(node.right != null) dfs(node.right);
  }
  dfs(root);
  // 暴力
  let lenA = arr.length,map = new Map();
  for(let i = 0; i < lenA; i++) {
    map.set(arr[i], i);
  }
  let color = new Array(lenA).fill(0);
  for(const [type, x, y] of ops) {
    let left = map.get(x);
    let right = map.get(y);
    for(let i = left;i <= right; i++) {
      color[i] = type;
    }
  }
  let ans = 0;
  color.forEach(col => col > 0 && ans++);
  return ans;
};

总结

  • 中等题,线段树的比较难写,js可以使用map集合的映射解决本题。