原题链接:230. Kth Smallest Element in a BST
【思路-Java、Python】——递归实现
我们知道二分查找数(BST)的性质——任何一个节点的值均大于左子树的任意节点值,而小于右子树的任一节点值。那么这样就可以知道最小值的一个节点在树的最左端,最大值的一个节点在树的最右端。树从小到大顺序刚好满足树的中序遍历。因而,我们可以用中序遍历来处理。
由于 k 是个基本类型的数,我们知道它与应用类型不同,本轮递归的 k 值改变不会引起下一轮的改变,那么我们的处理办法可以增加一个全局变量、增加一个引用变量或增加一个方法形参,用这样的参数记录目前遍历到的是第几小的数,本题采用增加一个局部变量的方法:
public class Solution {91 / 91 test cases passed. Runtime: 1 ms Your runtime beats 46.33% of javasubmissions.
private int count, res;
public int kthSmallest(TreeNode root, int k) {
if (root.left != null) kthSmallest(root.left, k);
if (++count == k) res = root.val; //①
if (root.right != null) kthSmallest(root.right, k);
return res;
}
}
class Solution(object):91 / 91 test cases passed. Runtime: 100 ms Your runtime beats 25.55% of pythonsubmissions.
def kthSmallest(self, root, k):
"""
:type root: TreeNode
:type k: int
:rtype: int
"""
global res, count
res,count = 0,0
def dfs(root, k) :
if not root : return
dfs(root.left, k)
global count, res
count += 1
if count == k : res = root.val //①
dfs(root.right, k)
dfs(root,k)
return res
【思路-Java、Python】——非递归实现
非递归实现需要用到一个栈,如果对非递归和递归遍历实现不是很熟悉可以参考我的另外一篇博文:
public class Solution {91 / 91 test cases passed. Runtime: 2 ms Your runtime beats 16.50% of javasubmissions.
public int kthSmallest(TreeNode root, int k) {
int ret = 0;
Stack<TreeNode> stack = new Stack<TreeNode>();
while(true) {
while(root != null) {
stack.push(root);
root = root.left;
}
if (stack.isEmpty()) break;
root = stack.pop();
if (--k == 0) return root.val; //②
root = root.right;
}
return 0;
}
class Solution(object):91 / 91 test cases passed. Runtime: 84 ms Your runtime beats 72.03% of pythonsubmissions.
def kthSmallest(self, root, k):
"""
:type root: TreeNode
:type k: int
:rtype: int
"""
stack = []
res = 0
while 1 :
while root :
stack.append(root)
root = root.left
if not stack : break
root = stack.pop()
k -= 1
if k == 0 : return root.val //②
root = root.right
return 0
就时间复杂度而言,时间复杂度的对比,通过本题递归和非递归的对比,我们可以简单看出递归和非递归的区别。在递归中,我们不能“终止递归”,即使采用 return也无法终止递归,为此,采用递归必须遍历完每个节点,为此我们采用①记录找到的那个节点,时间复杂度为O(n)。而非递归不同,如果找到了第 k 大的那个节点我们就直接用② return返回了。我们可以看到递归效率不一定比非递归低,如本题。实际上空间复杂度,忽略方法的压栈等操作,并且临时变量能被立即释放的话,递归的空间复杂度还更低。
本题的基础还是树的递归和非递归:
leetcode 94. Binary Tree Inorder Traversal 、leetcode 144. Binary Tree Preorder Traversal
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。