309, 二叉搜索树中第K小的元素

给定一个二叉搜索树,编写一个函数 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

答案:

 1public int kthSmallest(TreeNode root, int k) {
2    ArrayList<Integer> buffer = new ArrayList<Integer>();
3    inorderSearch(root, buffer, k);
4    return buffer.get(k - 1);
5}
6
7public void inorderSearch(TreeNode node, ArrayList<Integer> buffer, int k) {
8    if (buffer.size() >= k)
9        return;
10    if (node.left != null) {
11        inorderSearch(node.left, buffer, k);
12    }
13    buffer.add(node.val);
14    if (node.right != null) {
15        inorderSearch(node.right, buffer, k);
16    }
17}

解析:

首先我们要明白什么是二叉搜索树,二叉搜索树的定义是,若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉排序树。知道二叉搜索树的定义,上面代码就很容易理解了。他的写法就是DFS,先把最小的节点放到list中,然后是倒数第二小的……,直到第k个,也就是第k个最小的元素。我们再来看一个非递归的写法

 1public int kthSmallest(TreeNode root, int k) {
2    Stack<TreeNode> stack = new Stack<TreeNode>();
3    TreeNode p = root;
4    int count = 0;
5
6    while (!stack.isEmpty() || p != null) {
7        if (p != null) {
8            stack.push(p);
9            p = p.left;
10        } else {
11            TreeNode node = stack.pop();
12            if (++count == k)
13                return node.val;
14            p = node.right;
15        }
16    }
17    return Integer.MIN_VALUE;
18}

这题比较简单,解法也比较多,我们再来看一种写法,

 1int count = 0;
2int result = Integer.MIN_VALUE;
3
4public int kthSmallest(TreeNode root, int k) {
5    traverse(root, k);
6    return result;
7}
8
9public void traverse(TreeNode root, int k) {
10    if (root == null)
11        return;
12    traverse(root.left, k);
13    count++;
14    if (count == k) {
15        result = root.val;
16        return;
17    }
18    traverse(root.right, k);
19}

这种解法也比较简单,也很好理解,下面我们再来看一种解法

 1public int kthSmallest(TreeNode root, int k) {
2    Stack<TreeNode> st = new Stack<>();
3    while (root != null) {
4        st.push(root);
5        root = root.left;
6    }
7    while (k != 0) {
8        TreeNode n = st.pop();
9        k--;
10        if (k == 0)
11            return n.val;
12        TreeNode right = n.right;
13        while (right != null) {
14            st.push(right);
15            right = right.left;
16        }
17    }
18    return -1;
19}

这种解法也比较经典,第8行每次pop的都是最小的,如果能看明白这个就比较简单了,再来看一种解法

 1private static int number = 0;
2private static int count = 0;
3
4public int kthSmallest(TreeNode root, int k) {
5    count = k;
6    helper(root);
7    return number;
8}
9
10public void helper(TreeNode n) {
11    if (n.left != null)
12        helper(n.left);
13    count--;
14    if (count == 0) {
15        number = n.val;
16        return;
17    }
18    if (n.right != null)
19        helper(n.right);
20}

这个就不说了,和上面第3中很像,我们来看最后一种解法。

 1public int kthSmallest(TreeNode root, int k) {
2    int count = countNodes(root.left);
3    if (k <= count) {
4        return kthSmallest(root.left, k);
5    } else if (k > count + 1) {
6        return kthSmallest(root.right, k - 1 - count);
7    }
8    return root.val;
9}
10
11public int countNodes(TreeNode n) {//计算节点个数
12    if (n == null)
13        return 0;
14    return 1 + countNodes(n.left) + countNodes(n.right);
15}
上一篇:【leetcode】309. 最佳买卖股票时机含冷冻期


下一篇:【Leetcode】309. 买卖股票的最佳时机含冷冻期