剑指 Offer 54. 二叉搜索树的第k大节点
题目:
思路:
【1】拿到树或者链表的话其实少不了是要遍历的,而树的遍历存在三种:先序遍历(根左右),中序遍历(左根右),后序遍历(左右根)。而我们发现如果是数字的话其实中序遍历是最符合我们的要求的。如:
【2】基于中序遍历,将数据按顺序放入数组中。
【3】进行优化:1.首先题目求得是第几个,所以不一定要存入数组,其次,如果树很大,那边左边的遍历其实是无用的,所以可以考虑将顺序倒转,如左根右变为,右根左,形成数组的倒排。而且一旦遍历到了目标结果后立马中断遍历,不做额外的工作,减少消耗。
代码展示:
优化之后:
//时间0 ms击败100% //内存41.4 MB击败49.49% class Solution { int res, k; public int kthLargest(TreeNode root, int k) { this.k = k; dfs(root); return res; } void dfs(TreeNode root) { if(root == null) return; dfs(root.right); if(k == 0) return; if(--k == 0) res = root.val; dfs(root.left); } }
基于中序遍历,将数据按顺序放入数组中:这种理论上时间和空间辅助度都为O(N),因为遍历了整棵树,调用栈也是这么多。
//时间1 ms击败32.21% //内存42.1 MB击败9.68% /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ class Solution { public int kthLargest(TreeNode root, int k) { List<Integer> list=new ArrayList<>(); inOrder(root,list); int i=list.size()-k; return list.get(i); } public void inOrder(TreeNode root,List<Integer> list){ if(root == null) return; inOrder(root.left,list); list.add(root.val); inOrder(root.right,list); } }