1. 程式人生 > >二叉樹系列---在二叉樹中找到兩個節點的最近公共祖先

二叉樹系列---在二叉樹中找到兩個節點的最近公共祖先

題目

給定一顆二叉樹的頭結點,和這顆二叉樹中2個節點n1和n2,求這兩個節點的最近公共祖先;

思路

利用後序遍歷實現;
對於當前節點cur,如果節點為null或者等於n1或n2中的一個,則直接返回cur;
先處理左右子樹,左子樹返回left,右子樹返回right;判斷left和right;
1)left和right均為null,說明以cur為根的樹上沒發現n1和n2;
2)left和right均不為null,說明在左子樹上發現了n1或n2,在右子樹上也發現了n1或n2,cur為n1和n2的首次相遇節點,則直接返回cur;
3)left和right中一個null,另一個不為null,說明不為空的節點是n1和n2的其中一個,或者是n1和n2的最近公共祖先;則返回不為空的節點;

實現

package binary_tree;

/**
 * 求2個節點的最近公共祖先節點
 * @author fxx
 *
 */
public class LowestAncestor {

    /*求解n1和n1的最近公共祖先
     * 
     * 利用後序遍歷求解
     */
    public Node getLowestAncestor(Node head,Node n1,Node n2){
        if(head==null || head==n1 || head==n2){
            return head;
        }

        //先遍歷左右子樹,左右子樹的返回為left和right;然後判斷left和right請情況
Node left=getLowestAncestor(head.left,n1,n2); Node right=getLowestAncestor(head.right,n1,n2); /*左和右都不為null---說明在左子樹中發現過n1或n2, * 在右子樹上也發現過n1或n2,並且n1和n2在當前節點首次相遇 */ if(left!=null && right!=null){ return head; } /*左和右中一個不為null,另一個為null, * 說明不為null的節點是n1或n2中的一個,或者是n1和n2的最近祖先; * 直接返回; */
if(left!=null){ return left; } if(right!=null){ return right; } //左和右均為null,沒有發現n1和n2; return null; } }

改進1

建立一個結構hashMap:每個節點對應的父節點;
查詢公共祖先的過程:
先查詢hashMap,將n1和n1的祖先節點找出並放入另一個雜湊表A中,從n2開始向上移動,如果在A中發現了當前節點,則返回,否則向上移動;

package binary_tree;

import java.util.HashMap;
import java.util.HashSet;

public class LowestAncestor2 {

    private HashMap<Node,Node> map;//存放每個節點對應的父節點

    public LowestAncestor2(Node head){
        map=new HashMap<Node,Node>();
        if(head!=null){
            map.put(head, null);
        }
        setMap(head);
    }

    private void setMap(Node head) {
        if(head==null){
            return;
        }
        if(head.left!=null){
            map.put(head.left, head);
        }
        if(head.right!=null){
            map.put(head.right,head);
        }
        setMap(head.left);
        setMap(head.right);

    }

    public Node getLowestAncestor(Node root,Node n1,Node n2){
        HashSet<Node> set=new HashSet<Node>();
        while(map.containsKey(n1)){
            set.add(n1);
            n1=map.get(n1);
        }
        while(!set.contains(n2)){
            n2=map.get(n2);
        }
        return n2;
    }
}

測試

/**
     * @param args
     */
    public static void main(String[] args) {
        LowestAncestor LA=new LowestAncestor();
        Node head=LA.buildTree();
        Node node=LA.getLowestAncestor(head, head.left.left,head.right.right.right);
        System.out.println(node.value);

    }

    private Node buildTree(){
        Node head=new Node(1);
        head.left=new Node(2);
        head.right=new Node(3);

        head.left.left=new Node(4);
        head.left.right=new Node(5);

        head.right.left=new Node(6);
        head.right.right=new Node(7);

        head.right.right.right=new Node(8);

        return head;
    }