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:

    1. Consider implement these two helper functions:
      1. getPredecessor(N), which returns the next smaller node to N.
      2. 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 }

 

posted @ 2017-03-24 02:57  CodesKiller  阅读(198)  评论(0编辑  收藏  举报