剑指offer-二叉搜索树的第k个结点

题目描述

  • 给定一颗二叉搜索树,请找出其中的第k大的结点。例如, 5 / \ 3 7 /\ /\ 2 4 6 8 中,按结点数值大小顺序第三个结点的值为4。
  • 地址:牛客链接

问题分析

  • 因为是二叉搜索树,所以对它进行中序遍历得到的结果便是一个有序数列,从而很好找到第K个节点。
  • 但对于这题,我们只要找到第K个节点便可以停止,无需遍历所有节点,具体有以下两种做法:
    • 递归法:只需在原中序遍历递归版的基础上,在打印字符的那一处,改为count++,并确定当前count是否已经达到K即可。TreeNode KthNode(TreeNode pRoot, int[] count, int k)表示在已经查找到了count[0]个节点之后,查找第K个节点,具体细节见实现
    • 非递归法用栈来实现中序遍历的非递归,同样在打印字符的那一处,改为count++,并确定当前count是否已经达到K即可。具体见实现

经验教训

  • 二叉搜索树中序遍历的性质
  • 二叉树三大遍历的递归写法,以及非递归写法

代码实现

  • 递归法
    TreeNode KthNode(TreeNode pRoot, int k) {
        if (pRoot == null || k <= 0) {
            return null;
        }
        int[] count = new int[1];
        return KthNode(pRoot, count, k);
    }

    //在已经查找到了count[0]个节点之后,查找第K个节点
    TreeNode KthNode(TreeNode pRoot, int[] count, int k) {
        if (pRoot == null) {
            return null;
        }
        //在左子树上查找
        TreeNode leftRes = KthNode(pRoot.left, count, k);
        //左子树上已经查找到了第K个节点
        if (leftRes != null) {
            return leftRes;
        }
        //左子树上查找失败,查找根
        count[0]++;
        if (count[0] == k) {
            return pRoot;
        }
        //还不到K个,查找右子树
        return KthNode(pRoot.right, count, k);
    }
  • 非递归法
    TreeNode KthNode(TreeNode pRoot, int k) {
        if (pRoot == null || k <= 0) {
            return null;
        }
        Stack<TreeNode> stack = new Stack<>();
        TreeNode curNode = pRoot;
        int count = 0;
        while (curNode != null || ! stack.isEmpty()) {
            while (curNode != null) {
                stack.push(curNode);
                curNode = curNode.left;
            }
            curNode = stack.pop();
            //已经找到第K个节点
            if (++count == k) {
                return curNode;
            }
            curNode = curNode.right;
        }
        return null;
    }

你可能感兴趣的:(剑指offer,剑指offer(Java版))