算法小抄学习笔记 — 5.二叉搜索树(一)

本文介绍二叉搜索树的基础概念与特性,并通过两道典型题目:查找第k小的元素及转换为累加树,展示其在算法题中的应用技巧。

1 二叉搜索树的定义

二叉搜索树(Binary Search Tree)简称BST,对于BST中的每一个节点node:

  • 如果左子树的值都比node小。

  • 右子树的值都比node大。

那么这颗树为二叉搜索树。



2 二叉搜索树的性质

中序遍历递增,很多二叉搜索树的题目都是基于这一性质来展开的,很重要。

void traverse(TreeNode root) {
    if (root == null) return;
    traverse(root.left);
    // 中序遍历代码位置
    print(root.val);
    traverse(root.right);
}

当然,既然可以递增遍历,那么可不可以递减遍历呢? 当然可以,只需要将left和right顺序置换一下就可以了,下面有道题目就是需要递减遍历。

void traverse(TreeNode root) {
    if (root == null) return;
    traverse(root.right);
    // 中序遍历代码位置
    print(root.val);
    traverse(root.left);
}



3 题目

3.1 230. 二叉搜索树中第K小的元素

3.1.1 题目

给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素。

说明:
你可以假设 k 总是有效的,1 ≤ k ≤ 二叉搜索树元素个数。

示例 1:

输入: root = [3,1,4,null,2], k = 1
   3
  / \
 1   4
  \
   2
输出: 1

示例 2:

输入: root = [5,3,6,2,4,null,null,1], k = 3
       5
      / \
     3   6
    / \
   2   4
  /
 1
输出: 3
3.1.2 思路

由于是二叉搜索树相关的题目,首先就应该想起BST的性质:中序遍历递增,既然如此,中序遍历中第k次被访问的节点就为第k小的节点。

3.1.3 代码
class Solution {
    int res = 0;
    int rank = 0;
    public int kthSmallest(TreeNode root, int k) {
        traverse(root, k);
        return res;
    }

    void traverse(TreeNode root, int k) {
        if (root == null) {
            return;
        }

        traverse(root.left, k);

        /* ---- 中序遍历位置 ---- */
        rank++;
        if (rank == k) {
            res = root.val;
            return;
        } 
        /*************************/

        traverse(root.right, k);
    }
}

3.2 538. 把二叉搜索树转换为累加树

3.2.1 题目

给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。

提醒一下,二叉搜索树满足下列约束条件:

  • 节点的左子树仅包含键 小于 节点键的节点。
  • 节点的右子树仅包含键 大于 节点键的节点。
  • 左右子树也必须是二叉搜索树。

**注意:**本题和 1038: https://leetcode-cn.com/problems/binary-search-tree-to-greater-sum-tree/ 相同

示例 1:

img

输入:[4,1,6,0,2,5,7,null,null,null,3,null,null,null,8]
输出:[30,36,21,36,35,26,15,null,null,null,33,null,null,null,8]

示例 2:

输入:root = [0,null,1]
输出:[1,null,1]

示例 3:

输入:root = [1,0,2]
输出:[3,3,2]

示例 4:

输入:root = [3,2,4,1]
输出:[7,9,4,10]
3.2.2 思路

题目中所指的累加树是指当前节点的值为树中大于或等于该节点的值,而原树却是一个二叉搜索树,那么可以从树中从大至小依次遍历,依次累加替换当前节点的值。

根据二叉搜索树的性质,可以想到使用中序遍历的递减形式。

首先,只有清楚了函数的功能以及返回值的意义,才能够快速帮助我们理解递归函数本身,我认为这是非常重要的一步。

  • 函数的功能,传入当前节点root与遍历的累加值sum,替换当前节点的值。

  • 函数的返回值,以当前节点为根的树的累加值。

这样,如何用代码写出该题就清晰起来了。

3.2.3 代码
class Solution {
    public TreeNode convertBST(TreeNode root) {
        traverse(root, 0);
        return root;
    }

    int traverse(TreeNode root, int sum) {
        if (root == null) {
            return sum;
        }

        int rightSum = traverse(root.right, sum);
        
        /* ---- 中序遍历位置 ----*/
        root.val += rightSum;
        /************************/

        return traverse(root.left, root.val);
    }
}



4 参考

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值