272. Closest Binary Search Tree Value II
Given a non-empty binary search tree and a target value, find k values in the BST that are closest to the target.
Note:
- Given target value is a floating point.
- You may assume k is always valid, that is: k ≤ total nodes.
- You are guaranteed to have only one unique set of k values in the BST that are closest to the target.
Follow up:
Assume that the BST is balanced, could you solve it in less than O(n) runtime (where n = total nodes)?
Hint:
- Consider implement these two helper functions:
getPredecessor(N)
, which returns the next smaller node to N.getSuccessor(N)
, which returns the next larger node to N.
本题还是比较难的,先说常规方法,首先把树分成两部分,一个是小于target的,一个是大于等于target的,然后进行比较,找出k个接近target的k个值,代码如下:
1 /** 2 * Definition for a binary tree node. 3 * public class TreeNode { 4 * int val; 5 * TreeNode left; 6 * TreeNode right; 7 * TreeNode(int x) { val = x; } 8 * } 9 */ 10 public class Solution { 11 public List<Integer> closestKValues(TreeNode root, double target, int k) { 12 List<Integer> res = new ArrayList<Integer>(); 13 Stack<Integer> s1 = new Stack<Integer>(); 14 Stack<Integer> s2 = new Stack<Integer>(); 15 Inorder(s1,false,root,target); 16 Inorder(s2,true,root,target); 17 while(k-->0){ 18 if(s1.isEmpty()){ 19 res.add(s2.pop()); 20 }else if(s2.isEmpty()){ 21 res.add(s1.pop()); 22 }else if(Math.abs(s1.peek()-target)<Math.abs(s2.peek()-target)){ 23 res.add(s1.pop()); 24 }else{ 25 res.add(s2.pop()); 26 } 27 } 28 return res; 29 } 30 public void Inorder(Stack<Integer> s,boolean reverse,TreeNode root,double target){ 31 if(root==null) return; 32 Inorder(s,reverse,reverse?root.left:root.right,target); 33 if((reverse&&(root.val>target))||(!reverse&&(root.val<=target))) return; 34 s.push(root.val); 35 Inorder(s,reverse,reverse?root.right:root.left,target); 36 } 37 }
然而此方法的时间复杂度并没有减少,时间复杂度为O(n+k),所以有了动态的优化方法:
思路是,创建四个方法,分别有两个初始化,两个获取下一个方法。初始化的作用是找到target最近的较大和较小TreeNode,同时如果在过程中的也满足条件,把其放入stack中。获取下一个方法是,获取后,转其对应的另外子树,同时遍历一个h,代码如下:
1 /** 2 * Definition for a binary tree node. 3 * public class TreeNode { 4 * int val; 5 * TreeNode left; 6 * TreeNode right; 7 * TreeNode(int x) { val = x; } 8 * } 9 */ 10 public class Solution { 11 public List<Integer> closestKValues(TreeNode root, double target, int k) { 12 List<Integer> res = new ArrayList<Integer>(); 13 Stack<TreeNode> succ = new Stack<TreeNode>(); 14 Stack<TreeNode> pre = new Stack<TreeNode>(); 15 initalizesucc(root,target,succ); 16 initalizepre(root,target,pre); 17 if(!succ.isEmpty()&&!pre.isEmpty()&&succ.peek().val==pre.peek().val){ 18 getNextpre(pre); 19 } 20 while(k-->0){ 21 if(succ.isEmpty()){ 22 res.add(getNextpre(pre)); 23 }else if(pre.isEmpty()){ 24 res.add(getNextsucc(succ)); 25 }else{ 26 double succ_diff = Math.abs((double)succ.peek().val-target); 27 double pre_diff = Math.abs((double)pre.peek().val-target); 28 if(succ_diff<pre_diff){ 29 res.add(getNextsucc(succ)); 30 }else{ 31 res.add(getNextpre(pre)); 32 } 33 } 34 } 35 return res; 36 } 37 public void initalizesucc(TreeNode root,double target,Stack<TreeNode> succ){ 38 while(root!=null){ 39 if(root.val==target){ 40 succ.push(root); 41 break; 42 }else if(root.val<target){ 43 root = root.right; 44 }else{ 45 succ.push(root); 46 root = root.left; 47 } 48 } 49 } 50 public void initalizepre(TreeNode root,double target,Stack<TreeNode> pre){ 51 while(root!=null){ 52 if(root.val==target){ 53 pre.push(root); 54 break; 55 }else if(root.val<target){ 56 pre.push(root); 57 root = root.right; 58 }else{ 59 root = root.left; 60 } 61 } 62 } 63 public int getNextsucc(Stack<TreeNode> stack){ 64 TreeNode succ = stack.pop(); 65 int val = succ.val; 66 succ = succ.right; 67 while(succ!=null){ 68 stack.push(succ); 69 succ = succ.left; 70 } 71 return val; 72 } 73 public int getNextpre(Stack<TreeNode> stack){ 74 TreeNode pre = stack.pop(); 75 int val = pre.val; 76 pre = pre.left; 77 while(pre!=null){ 78 stack.push(pre); 79 pre = pre.right; 80 } 81 return val; 82 } 83 }