LeetCode.993-二叉樹中的堂兄弟(Cousins in Binary Tree)

這是悅樂書的第374次更新,第401篇原創

java

01 看題和準備

今天介紹的是LeetCode算法題中Easy級別的第235題(順位題號是993)。在二叉樹中,根節點在深度0處,而且每一個深度爲k的節點的子節點,他們深度爲k + 1node

若是二元樹的兩個節點具備相同的深度但具備不一樣的父節點,則它們是堂兄弟。算法

咱們給出了具備惟一值的二叉樹root,以及樹中兩個不一樣節點的值xy數組

當且僅當對應於值x和y的節點是堂兄弟時,才返回true。例如:數據結構

輸入:root = [1,2,3,4],x = 4,y = 3code

1
    /   \
   2     3
  / 
 4

輸出:false


輸入:root = [1,2,3,null,4,null,5],x = 5,y = 4遞歸

1
    /   \
   2     3
    \     \
     4     5

輸出:true


輸入:root = [1,2,3,null,4],x = 2,y = 3隊列

1
    /   \
   2     3
    \ 
     4

輸出:falseget

注意it

  • 樹中的節點數將介於2和100之間。

  • 每一個節點都有一個從1到100的惟一整數值。

02 第一種解法

題目的意思是xy在同一層,可是他們的父級節點不同,也就是xy屬於堂兄弟的關係。

使用BFS(廣度優先)的算法,經過迭代的方式藉助Stack來實現,使用了一個額外的方法,分別求出xy的層級和他們的父級節點,用一個長度爲2的數組返回,若是xy的層級相同且父級結點不一樣,就返回true

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

public boolean isCousins(TreeNode root, int x, int y) {
    int[] arr = getTreeDepth(root, x);
    int[] arr2 = getTreeDepth(root, y);
    if (arr.length < 1 || arr2.length < 1) {
        return false;
    }
    return arr[0] != arr2[0] && arr[1] == arr2[1];
}

public int[] getTreeDepth(TreeNode root, int num) {
    Stack<TreeNode> stack = new Stack<TreeNode>();
    stack.push(root);
    int depth = 0;
    while (!stack.isEmpty()) {
        Stack<TreeNode> stack2 = new Stack<TreeNode>();
        while (!stack.isEmpty()) {
            TreeNode tem = stack.pop();
            if (tem.left != null) {
                // 當前節點的左子節點值等於要找的數
                if (tem.left.val == num) {
                    return new int[] {tem.val, depth+1};
                }
                stack2.push(tem.left);
            }
            if (tem.right != null) {
                // 當前節點的右子節點值等於要找的數
                if (tem.right.val == num) {
                    return new int[] {tem.val, depth+1};
                }
                stack2.push(tem.right);
            }
        }
        stack = stack2;
        depth++;
    }
    return new int[] {};
}


03 第二種解法

針對第一種解法,咱們也能夠將判斷的方法融合在一塊兒,依舊是藉助

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

public boolean isCousins2(TreeNode root, int x, int y) {
    Stack<TreeNode> stack = new Stack<TreeNode>();
    stack.push(root);
    while (!stack.isEmpty()) {
        Stack<TreeNode> stack2 = new Stack<TreeNode>();
        boolean xExist = false, yExist = false;
        while (!stack.isEmpty()) {
            TreeNode tem = stack.pop();
            if (tem.val == x) {
                xExist = true;
            }
            if (tem.val == y) {
                yExist = true;
            }
            // x和y不能有同一個父節點
            if (tem.left != null && tem.right != null) {
                if (tem.left.val == x && tem.right.val == y) {
                    return false;
                }
                if (tem.left.val == y && tem.right.val == x) {
                    return false;
                }
            }
            if (tem.left != null) {
                stack2.push(tem.left);
            }
            if (tem.right != null) {
                stack2.push(tem.right);
            }
        }
        stack = stack2;
        if (xExist && yExist) {
            return true;
        }
    }
    return false;
}


04 第三種解法

和第二種解法思路同樣,只是將棧換成了隊列

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

public boolean isCousins3(TreeNode root, int x, int y) {
    Queue<TreeNode> queue = new LinkedList<>();
    queue.offer(root);
    while (!queue.isEmpty()) {
        int size = queue.size();
        boolean xExist = false, yExist = false;
        for (int i=0; i<size; i++) {
            TreeNode tem = queue.poll();
            if (tem.val == x) {
                xExist = true;
            }
            if (tem.val == y) {
                yExist = true;
            }
            // x和y不能有同一個父節點
            if (tem.left != null && tem.right != null) {
                if (tem.left.val == x && tem.right.val == y) {
                    return false;
                }
                if (tem.left.val == y && tem.right.val == x) {
                    return false;
                }
            }
            if (tem.left != null) {
                queue.offer(tem.left);
            }
            if (tem.right != null) {
                queue.offer(tem.right);
            }
        }
        if (xExist && yExist) {
            return true;
        }
    }
    return false;
}


05 第四種解法

藉助遞歸,一個遞歸方法求深度,一個遞歸方法找父節點,最後判斷深度是否相同且父節點不一樣。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

public boolean isCousins4(TreeNode root, int x, int y) {
    return getDepth(root, x, 0) == getDepth(root, y, 0) && 
            findParent(root, x) != findParent(root, y);
}

public int getDepth(TreeNode root, int num, int depth){
    if (root == null) {
        return 0;
    }
    if (root.val == num) {
        return depth;
    }
    int left = getDepth(root.left, num, depth+1);
    int right = getDepth(root.right, num, depth+1);
    return Math.max(left, right);
}

public int findParent(TreeNode root, int num) {
    if (root == null) {
        return 0;
    }
    if (root.left != null && root.left.val == num) {
        return root.val;
    }
    if (root.right != null && root.right.val == num) {
        return root.val;
    }
    int left = findParent(root.left, num);
    int right = findParent(root.right, num);
    return Math.max(left, right);
}


06 第五種解法

咱們也能夠只是用一次遞歸方法,藉助全局變量來解。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

private int depthX;
private int depthY;
private TreeNode parentX;
private TreeNode parentY;

public boolean isCousins5(TreeNode root, int x, int y) {
    helper(root, x, y, 0, null);
    return depthX == depthY && parentX != parentY;
}

public void helper(TreeNode root, int x, int y, int depth, TreeNode parent) {
    if (root == null) {
        return ;
    }
    if (root.val == x) {
        depthX = depth;
        parentX = parent;
    } else if (root.val == y) {
        depthY = depth;
        parentY = parent;
    }
    helper(root.left, x, y, depth+1, root);
    helper(root.right, x, y, depth+1, root);
}


07 第六種解法

咱們還能夠將第五種解法中找父節點的變量換成int類型,由於節點值惟一,能夠直接使用節點值參與判斷。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

private int depthX;
private int depthY;
private int parentX;
private int parentY;

public boolean isCousins6(TreeNode root, int x, int y) {
    helper(root, x, y, 0, 0);
    return depthX == depthY && parentX != parentY;
}

public void helper(TreeNode root, int x, int y, int depth, int parent) {
    if (root == null) {
        return ;
    }
    if (root.val == x) {
        depthX = depth;
        parentX = parent;
    } else if (root.val == y) {
        depthY = depth;
        parentY = parent;
    }
    helper(root.left, x, y, depth+1, root.val);
    helper(root.right, x, y, depth+1, root.val);
}


08 小結

算法專題目前已連續日更超過七個月,算法題文章241+篇,公衆號對話框回覆【數據結構與算法】、【算法】、【數據結構】中的任一關鍵詞,獲取系列文章合集。

以上就是所有內容,若是你們有什麼好的解法思路、建議或者其餘問題,能夠下方留言交流,點贊、留言、轉發就是對我最大的回報和支持!

相關文章
相關標籤/搜索