zoukankan      html  css  js  c++  java
  • 给定一个二叉搜索树(BST),找到树中第 K 小的节点

    题目:给定一个二叉搜索树(BST),找到树中第 K 小的节点。

    * 考察点

    1. 基础数据结构的理解和编码能力
    2. 递归使用

    * 示例

           5
          / 
         3   6
        / 
       2   4
      /
     1
     
    

    说明:保证输入的 K 满足 1<=K<=(节点数目)

    树相关的题目,第一眼就想到递归求解,左右子树分别遍历。联想到二叉搜索树的性质,root 大于左子树,小于右子树,如果左子树的节点数目等于 K-1,那么 root 就是结果,否则如果左子树节点数目小于 K-1,那么结果必然在右子树,否则就在左子树。因此在搜索的时候同时返回节点数目,跟 K 做对比,就能得出结果了。

    /**
     * Definition for a binary tree node.
     **/
    
    public class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode(int x) { val = x; }
    }
    
    class Solution {
        private class ResultType {
        
            boolean found;  // 是否找到
            
            int val;  // 节点数目
            ResultType(boolean found, int val) {
                this.found = found;
                this.val = val;
            }
        }
    
        public int kthSmallest(TreeNode root, int k) {
            return kthSmallestHelper(root, k).val;
        }
    
        private ResultType kthSmallestHelper(TreeNode root, int k) {
            if (root == null) {
                return new ResultType(false, 0);
            }
    
            ResultType left = kthSmallestHelper(root.left, k);
    
            // 左子树找到,直接返回
            if (left.found) {
                return new ResultType(true, left.val);
            }
    
            // 左子树的节点数目 = K-1,结果为 root 的值
            if (k - left.val == 1) {
                return new ResultType(true, root.val);
            }
    
            // 右子树寻找
            ResultType right = kthSmallestHelper(root.right, k - left.val - 1);
            if (right.found) {
                return new ResultType(true, right.val);
            }
    
            // 没找到,返回节点总数
            return new ResultType(false, left.val + 1 + right.val);
        }
    }
    

    给定一个二叉搜索树,编写一个函数 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
    进阶:
    如果二叉搜索树经常被修改(插入/删除操作)并且你需要频繁地查找第 k 小的值,你将如何优化 kthSmallest 函数?

    使用中序遍历

    class Solution {
        List<Integer> list = new ArrayList();
        public void dfs(TreeNode root){
            if(root == null)
                return ;
            dfs(root.left);
            list.add(root.val);
            dfs(root.right);
        }
        public int kthSmallest(TreeNode root, int k) {
            dfs(root);
            for(int i=0;i<list.size();i++){
                if(i == k-1)
                    return list.get(i);
            }
            return -1;
        }
    }


    使用递归(计算节点数量):

    class Solution {    
        public int count(TreeNode root){
            if(root == null)
                return 0;
            return 1 + count(root.left) + count(root.right);
        }
        public int kthSmallest(TreeNode root, int k) {
            int num = count(root.left);
            if(num == k-1)
                return root.val;
            if(num > k-1)
                return kthSmallest(root.left,k);
            return kthSmallest(root.right,k - num-1);
        }
    }


    参考链接:

    https://blog.csdn.net/xuchonghao/article/details/80770490

    https://github.com/debitCrossBlockchain/interview__reference/blob/master/01.%E9%98%BF%E9%87%8C%E7%AF%87/1.1.3%20%E7%BB%99%E5%AE%9A%E4%B8%80%E4%B8%AA%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91(BST)%EF%BC%8C%E6%89%BE%E5%88%B0%E6%A0%91%E4%B8%AD%E7%AC%AC%20K%20%E5%B0%8F%E7%9A%84%E8%8A%82%E7%82%B9.md

  • 相关阅读:
    Jzoj1307 Jail
    Jzoj1307 Jail
    Jzoj1306 Sum
    Jzoj1306 Sum
    Jzoj1279 解题
    Jzoj1279 解题
    Jzoj1277最高的奶牛
    Jzoj1277最高的奶牛
    Jzoj1155 有根树的同构(树的Rabin-Karp)
    Jzoj1155 有根树的同构(树的Rabin-Karp)
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13312574.html
Copyright © 2011-2022 走看看