230. Kth Smallest Element in a BST

来源:互联网 发布:列宁格勒 知乎 编辑:程序博客网 时间:2024/05/17 03:23

题目:

Given a binary search tree, write a function kthSmallest to find the kth smallest element in it.

Note: 
You may assume k is always valid, 1 ≤ k ≤ BST's total elements.

Follow up:
What if the BST is modified (insert/delete operations) often and you need to find the kth smallest frequently? How would you optimize the kthSmallest routine?

Hint:

  1. Try to utilize the property of a BST.
  2. What if you could modify the BST node's structure?
  3. The optimal runtime complexity is O(height of BST).

题意:

给定一个二叉搜索树,写一个功能kthSmallest用来找到该二叉树中第K小的元素。

二叉搜索树:它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。即根节点的值是中间值,左子树的值均小于根节点的值,右子树的值均大于根节点的值。

note:

可以假设k总是有效的,1 ≤ k ≤二叉搜索树总的节点数量。

Follow up:

如果BST的修改(插入/删除)操作十分频繁,并且需要频繁地找出第k小的元素,应该怎样优化kthSmallest函数?

Hint:

1、尝试利用BST的属性。

2、如果你可以修改BST节点的结构时,应该怎样做?

3、最优时间复杂度应该是O(BST的高度)。


思路一:

利用堆栈实现,利用堆栈实现中序遍历,首先找到最左边的元素,即为该二叉搜索树的最小值,将从根节点开始的所有左子树的根节点都保存在堆栈中,以备左右子树切换时使用,每找到一个左子树叶子节点,则k减一,病切换到右子树去查询,直到k为0为止,返回该节点的值即可。非递归版。

代码:java版:2ms

/** * Definition for a binary tree node. * public class TreeNode { *     int val; *     TreeNode left; *     TreeNode right; *     TreeNode(int x) { val = x; } * } */public class Solution {    public int kthSmallest(TreeNode root, int k) {        Stack<TreeNode> stack = new Stack<TreeNode>();        TreeNode node = root;        while (node.left != null) { //将所有的左子树入栈            stack.push(node);            node = node.left;        }                while (k>0 && (node!=null || !stack.isEmpty())) {            if (node == null) {  //如果节点为空                node = stack.pop();  //找到其父节点                if (--k == 0) //找到第k小的元素                    return node.val;                node = node.right;  //找右子树            } else {                  stack.push(node);                node = node.left;            }        }        return node.val;    }}
代码:C++版:20ms

/** * Definition for a binary tree node. * struct TreeNode { *     int val; *     TreeNode *left; *     TreeNode *right; *     TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */class Solution {public:    int kthSmallest(TreeNode* root, int k) {        int cnt = 0;        stack<TreeNode*> s;        TreeNode *p = root;        while (p || !s.empty()) {            while (p) {                s.push(p);                p = p->left;            }            p = s.top();            s.pop();            ++cnt;            if (cnt == k)                return p->val;            p = p->right;        }        return 0;    }};


思路二:

利用计算二叉树节点数量的子函数,计算出根节点左子树的总的节点数量,然后比较左子树节点数量与k值得大小,如果k值小于左子树节点数目,则说明该值在左子树中,继续对左子树进行迭代处理,如果大于,则说明k值最小的节点在右子树中,则对右子树进行迭代处理,并且减掉前面左子树数目的k值。

代码:C++版:24ms

/** * Definition for a binary tree node. * struct TreeNode { *     int val; *     TreeNode *left; *     TreeNode *right; *     TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */class Solution {public:    int kthSmallest(TreeNode* root, int k) {        if (root == NULL) return 0;                int leftSize = treeSize(root->left);        if (k == leftSize+1) {            return root->val;        } else if (leftSize >= k) {            return kthSmallest(root->left, k);        } else {            return kthSmallest(root->right, k-leftSize-1);        }    }        int treeSize(TreeNode* root) {  //计算根节点下有多少节点        if (root == NULL) return 0;        return 1 + treeSize(root->left) + treeSize(root->right);    }};


思路三:

直接递归实现,依然基于中序遍历的思想。

代码:C++版:20ms

/** * Definition for a binary tree node. * struct TreeNode { *     int val; *     TreeNode *left; *     TreeNode *right; *     TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */class Solution {public:    int kthSmallest(TreeNode* root, int k) {        return kthSmallestDFS(root, k);    }    int kthSmallestDFS(TreeNode* root, int &k) {        if (!root) return -1;        int val = kthSmallestDFS(root->left, k);        if (!k)            return val;        if (!--k)             return root->val;        return kthSmallestDFS(root->right, k);    }};

0 0
原创粉丝点击