博客 / 詳情

返回

二叉樹遞歸套路(2):判斷二叉樹是否是搜索二叉樹、二叉樹的最大距離

本篇繼續來聊聊二叉樹的遞歸套路。

一、判斷二叉樹是否是搜索二叉樹

搜索二叉樹定義:二叉樹中的任意一個以X為頭的子樹,左子樹都比X小,右子樹都比X大。(經典的搜索二叉樹是沒有重複值的)

1、經典做法

中序遍歷,結果是遞增的,説明這是搜索二叉樹。

2、遞歸套路思路

分析任意一個以X為頭的子樹,滿足以X為頭的子樹是搜索二叉樹的條件(列出所有可能性

1)左子樹是搜索二叉樹

2)右子樹是搜索二叉樹

3)左子樹的最大值 小於 X

4)右子樹的最小值 大於 X

滿足這四個條件才能説以X為頭的子樹是平衡二叉樹。

問題來了:此時發現我需要從左子樹和右子樹中獲取的結果不一致(一個是要最小值、一個是要最大值),不好拼湊出遞歸。咋辦?好説,我們直接求全集(小孩子才做選擇,成年人不做選擇,都要),左子樹我們求最大值和最小值,右子樹也是。

也就是每次從左子樹和右子樹中我們都需要 是否搜索二叉樹、最大值、最小值 三個數據,儘管我們最後只返回是否搜索二叉樹,但是我們需要最大值和最小值來輔助我們判斷是否搜索,所以可以定義如下的Info類

/**
 * @author Java和算法學習:週一
 */
public static class Info {
    public boolean isSearch;
    public int max;
    public int min;

    public Info(boolean isSearch, int max, int min) {
        this.isSearch = isSearch;
        this.max = max;
        this.min = min;
    }
}

3、遞歸套路代碼

(1)首先判斷為空時好不好設置,此時不好設置,節點為空時max和min不好指定,所以節點為空時直接返回null,後面遞歸時再處理這個null即可。

(2)然後根據列出的所有可能性,編寫遞歸套路的代碼,因為要整個形成遞歸,所以每一步都要返回Info類。(無腦拿到左右子樹的Info、拼湊自己的Info、返回自己的Info)

/**
 * 判斷是否是搜索二叉樹的遞歸套路寫法
 *
 * @author Java和算法學習:週一
 */
public static Info process(Node x) {
    // 為空時,max和min無法賦值,所以此處返回null
    if (x == null) {
        return null;
    }

    // 獲取左右子樹的數據
    Info leftInfo = process(x.left);
    Info rightInfo = process(x.right);

    // 拼湊自己的數據
    boolean isSearch = true;
    // 當前節點不是搜索二叉樹的情況
    // 1.左子樹不是搜索二叉樹
    // 2.右子樹不是搜索二叉樹
    // 3.左子樹最大值大於當前節點
    // 4.右子樹最小值小於當前節點
    if (leftInfo != null && (!leftInfo.isSearch || leftInfo.max >= x.value)) {
        isSearch = false;
    }
    if (rightInfo != null && (!rightInfo.isSearch || rightInfo.min <= x.value)) {
        isSearch = false;
    }

    int max = x.value;
    int min = x.value;
    if (leftInfo != null) {
        max = Math.max(leftInfo.max, max);
        min = Math.min(leftInfo.min, min);
    }
    if (rightInfo != null) {
        max = Math.max(rightInfo.max, max);
        min = Math.min(rightInfo.min, min);
    }

    return new Info(isSearch, max, min);
}

(3)主函數調用遞歸方法獲取結果

/**
 * @author Java和算法學習:週一
 */
public static boolean isSearchBinaryTree(Node head) {
    if (head == null) {
        return true;
    }
    return process(head).isSearch;
}

所有代碼地址:

https://github.com/monday-pro...

二、二叉樹的最大距離

給定一個二叉樹,任何兩個節點之間都存在距離,返回整個二叉樹的最大距離。兩個節點的距離表示從一個節點到另一個節點最短路徑上的節點數(包含兩個節點自己)

1、遞歸套路思路

首先分析以X為頭的二叉樹,它的最大距離的可能性有兩類,不經過X、經過X。

image.png

不經過X:需要獲取左子樹和右子樹各自的最大距離

經過X:(左樹高度 + 右樹高度 + 1)即是最大距離

也就是每次從左子樹和右子樹中我們都需要 最大距離、高度 兩個數據,最後再取 左子樹最大距離、右子樹最大距離、(左樹高度 + 右樹高度 + 1) 的最大值即是整個樹的最大距離。儘管我們最後只返回最大距離,但是我們需要高度來輔助我們計算最大距離,所以可以定義如下的Info類

/**
 * @author Java和算法學習:週一
 */
public static class Info {
    public int height;
    public int maxDistance;

    public Info(int height, int maxDistance) {
        this.height = height;
        this.maxDistance = maxDistance;
    }
}

2、遞歸套路代碼

(1)首先判斷為空時好不好設置,此時是好設置的,節點為空時new Info(0, 0),即認為空節點高度為0、最大距離為0。

(2)然後根據列出的所有可能性,編寫遞歸套路的代碼,因為要整個形成遞歸,所以每一步都要返回Info類。(無腦拿到左右子樹的Info、拼湊自己的Info、返回自己的Info

/**
 * 求二叉樹的最大距離的遞歸套路寫法
 * 
 * @author Java和算法學習:週一
 */
public static Info process(Node x) {
    if (x == null) {
        return new Info(0, 0);
    }

    // 獲取左右子樹的信息
    Info leftInfo = process(x.left);
    Info rightInfo = process(x.right);

    // 拼湊處理自己的信息
    // 最大高度是 左右子樹最大高度 + 1
    int height = Math.max(leftInfo.height, rightInfo.height) + 1;
    // 最大距離是 左子樹最大距離、右子樹最大距離、(左樹高度 + 右樹高度 + 1) 三個的最大值
    int maxDistance = Math.max((leftInfo.height + rightInfo.height + 1),
            Math.max(leftInfo.maxDistance, rightInfo.maxDistance));

    return new Info(height, maxDistance);
}

(3)主函數調用遞歸方法獲取結果

/**
 * @author Java和算法學習:週一
 */
public static int maxDistance(Node head) {
    if (head == null) {
        return 0;
    }
    return process(head).maxDistance;
}

所有代碼地址:

https://github.com/monday-pro...

這是二叉樹遞歸套路解法的第二篇,結合上一篇是不是發現又有了新的收穫呢。這次我們又學會了左右子樹需要獲取的值不同時如何處理、在節點為空時不好設置值時如何處理等

user avatar shijianzhiwai_5f6ef74c5a46e 頭像 mofaboshi 頭像
2 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.