Problem description:
Given a Binary Tree and a key ‘k’, find distance of the closest leaf from ‘k’.
A / \ B C / \ E F / \ G H / \ / I J K Closest key to 'H' is 'K', so distance is 1 for 'H' Closest key to 'C' is 'B', so distance is 2 for 'C' Closest key to 'E' is either 'I' or 'J', so distance is 2 for 'E' Closest key to 'B' is 'B' itself, so distance is 0 for 'B'
Solution:
Find all the ancestry of the target node, and the min-depth of them. Distance from target to its ancestry, plus distance from ancestry to ancestry’s min-depth leaf is a potential result. Among them and the min-depth of the target node itself, find the smallest one.
The traversal process is:
For each node, it traverse the left and right sub-tree, and get the min-depth from each sub-tree. And it will return min-depth to its ancestry.
After traverse each sub-tree, if it found the target in either sub-tree, this node is treated as an ancestry of the target node. And the ancestry information should be stored.
In my code, I define a AncestryInfo class, to restore the ancestry information:
class AncestryInfo{
int[] ancestry_record; //records the ancestry nodes from target node. Target node is also included in position 0;
int[] ancestry_level; //records the min deep of ancestry nodes.
int[] leaf; //records the leaf which the ancestry nodes reach to the min deep
}
- public class FindNearestLeaf {
- public static void main(String[] args) {
- Tree tree = Tree.getTree();
- findNearestLeaf(tree, 7);
- System.out.println();
- }
- public static void findNearestLeaf(Tree tree, int value){
- AncestryInfo ancestry = new AncestryInfo();
- //traverse the tree, to find the relative information
- findNearestLeafUtil(tree, value, ancestry, new MyInteger(), new MyInteger(), new MyBoolean());
- int leaf = ancestry.leaf[0];
- int distance = ancestry.ancestry_level[0];
- for(int i=1;i
- if(i-0+ancestry.ancestry_level[i]
- distance = i-0+ancestry.ancestry_level[i];
- leaf = ancestry.leaf[i];
- }
- }
- distance–;
- System.out.println(“Nearest Leaf:” + leaf + “\tDistance:” + distance);
- }
- public static void findNearestLeafUtil(Tree root, int value, AncestryInfo anc, MyInteger depth, MyInteger leaf, MyBoolean found){
- if(root==null){
- return;
- }
- MyInteger l_depth = new MyInteger(Integer.MAX_VALUE);
- MyInteger r_depth = new MyInteger(Integer.MAX_VALUE);
- MyBoolean l_found = new MyBoolean();
- MyBoolean r_found = new MyBoolean();
- MyInteger l_leaf = new MyInteger();
- MyInteger r_leaf = new MyInteger();
- if(root.left!=null){
- findNearestLeafUtil(root.left, value, anc, l_depth, l_leaf, l_found);
- }
- if(root.right!=null){
- findNearestLeafUtil(root.right, value, anc, r_depth, r_leaf, r_found);
- }
- if(root.left==null&&root.right==null){ // current node is a leaf
- depth.i = 1;
- leaf.i = root.value;
- }
- else{ //if current node is not a leaf, get the depth from information of 2 sub tress.
- depth.i = Math.min(l_depth.i, r_depth.i) + 1;
- leaf.i = l_depth.i
- }
- found.bool = l_found.bool||r_found.bool;
- if(found.bool){
- //if the target node is already found, then current node is treated as an ancestry. So store the ancestry information.
- anc.ancestry_record = Arrays.copyOf(anc.ancestry_record, anc.ancestry_record.length+1);
- anc.ancestry_record[anc.ancestry_record.length-1] = root.value;
- anc.ancestry_level = Arrays.copyOf(anc.ancestry_level, anc.ancestry_level.length+1);
- anc.ancestry_level[anc.ancestry_level.length-1] = depth.i;
- anc.leaf = Arrays.copyOf(anc.leaf, anc.leaf.length+1);
- anc.leaf[anc.leaf.length-1] = leaf.i;
- return;
- }
- if(root.value==value){ //current node is the target, initial the ancestry information
- found.bool = true;
- anc.ancestry_record = new int[]{root.value};
- anc.ancestry_level = new int[]{depth.i};
- anc.leaf = new int[]{leaf.i};
- return;
- }
- return;
- }
- }
- class AncestryInfo{
- int[] ancestry_record; //records the ancestry nodes from target node. Target node is also included in position 0;
- int[] ancestry_level; //records the min deep of ancestry nodes.
- int[] leaf; //records the leaf which the ancestry nodes reach to the min deep
- }
- class MyBoolean {
- public boolean bool;
- public MyBoolean(boolean bool){
- this.bool = bool;
- }
- public MyBoolean(){
- this.bool = false;
- }
- public String toString(){
- return String.valueOf(bool);
- }
- }
- class MyInteger{
- public int i = 0;
- public MyInteger(int i){
- this.i = i;
- }
- public MyInteger(){}
- public String toString(){
- return String.valueOf(i);
- }
- }
- class Tree{
- public Tree(int value){
- this.value = value;
- }
- public Tree(String value){
- this.valueString = value;
- }
- public Tree left;
- public Tree right;
- public int value;
- public String valueString;
- public static Tree getTree(){
- Tree t18 = new Tree(18);
- Tree t17 = new Tree(17);
- Tree t16 = new Tree(16);
- Tree t15 = new Tree(15);
- Tree t14 = new Tree(14);
- Tree t13 = new Tree(13);
- Tree t12 = new Tree(12);
- Tree t11 = new Tree(11);
- Tree t10 = new Tree(10);
- Tree t9 = new Tree(9);
- Tree t8 = new Tree(8);
- Tree t7 = new Tree(7);
- Tree t6 = new Tree(6);
- Tree t5 = new Tree(5);
- Tree t4 = new Tree(4);
- Tree t3 = new Tree(3);
- Tree t2 = new Tree(2);
- Tree t1 = new Tree(1);
- t8.left = t9;
- t6.left = t8;
- t5.right = t7;
- t4.left = t5;
- t4.right = t6;
- t2.left = t4;
- t1.left = t2;
- t1.right = t3;
- t6.right = t10;
- t3.left = t11;
- t3.right = t12;
- t12.left = t13;
- t12.right = t14;
- t13.left = t15;
- t13.right = t16;
- t16.right = t17;
- t17.right = t18;
- return t1;
- }
- }