[LeetCode#270] Closest Binary Search Tree Value
Problem:
Given a non-empty binary search tree and a target value, find the value in the BST that is closest to the target.
Note:
- Given target value is a floating point.
- You are guaranteed to have only one unique value in the BST that is closest to the target.
Wrong solution 1:
public class Solution { public int closestValue(TreeNode root, double target) { if (root == null) throw new IllegalArgumentException("root is null"); int closest_gap = Integer.MAX_VALUE; int ret; while (root != null) { if (Math.abs(target - root.val) < closest_gap) { closest_gap = Math.abs(target - root.val); ret = root.val; } if (target == root.val) return root.val; else if (target < root.val) root = root.left; else root = root.right; } return ret; } }
Mistakes Analysis:
Line 18: error: incompatible types: possible lossy conversion from double to int Line 55: error: variable ret might not have been initialized Mistake 1: Even the problem has emphasized that target is a floating type, the val in node is Integer type. I still blindly ignore the fact that : the type used for recording the distance should be a float type rather than Integer. Otherwise, we could lose precision. Case : target = 0.3 val_1: -1, val_2: 1 (int)(target - val_1) = 1; (int)(target - val_2) = 1; Wrong Fix: double closest_gap = Integer.MAX_VALUE; ... if (Math.abs(target - (double)root.val) < closest_gap) { closest_gap = Math.abs(target - (double)root.val); ret = root.val; } ... Mistake 2: Since "ret" is a return value, and it was solely enclosed in if-else blocks, we must initialize it.
Wrong solution 2:
public class Solution { public int closestValue(TreeNode root, double target) { if (root == null) throw new IllegalArgumentException("root is null"); double closest_gap = Integer.MAX_VALUE; int ret = 0; while (root != null) { if (Math.abs(target - (double)root.val) <= closest_gap) { closest_gap = Math.abs(target - (double)root.val); ret = root.val; } if (target == root.val) return root.val; else if (target < root.val) root = root.left; else root = root.right; } return ret; } }
Mistakes Analysis:
Error Cases: [1500000000,1400000000], -1500000000.0 Output: 0 Expected: 1400000000 Mistake Analysis: Even though I have changed the type of "closet_gap" into double, I still fail to consider the single floating point "target" could have larger range than Integer, which would produce the distance larger than "Integer.MAX_VALUE". double closest_gap = Integer.MAX_VALUE; Fix: double closest_gap = Double.MAX_VALUE;
Skill:
Finally, we get it right!!! But this a good lesson for us to learn a important skill: avoiding overflow through more advanced primitive types. Actually, we have meet it many times : reverse Integer, convert String into Integer. We know: Whether "add" or "minus", we could easily exceed the operand's value range. Take Integer as example: Integer.MAX_VALUE + 1 overflow; Integer.MIN_VALUE - 1 overflow; Even the operation between Integer with Double could easily result in overflow problem. Double.MAX_VALUE + 1 overflow; Double.MIN_VALUE - 1 overflow. Thus we have to take advantage of advanced type!!! For the operations among Integer, we use long to hold the result. long res = integer1 + integer 2. For this problem, we were guaranteed that the target is a single floating point, it means we can use "double" to handle the result. <or for the maximum comparision> Note: closestValue(TreeNode root, double target) is a little misleading, but it is indeed a single floating point.
Solution:
public class Solution { public int closestValue(TreeNode root, double target) { if (root == null) throw new IllegalArgumentException("root is null"); double closest_gap = Double.MAX_VALUE; int ret = 0; while (root != null) { if (Math.abs(target - (double)root.val) <= closest_gap) { closest_gap = Math.abs(target - (double)root.val); ret = root.val; } if (target == root.val) return root.val; else if (target < root.val) root = root.left; else root = root.right; } return ret; } }