每日演算法之樹的子結構

来源:https://www.cnblogs.com/loongnuts/archive/2022/12/03/16947136.html
-Advertisement-
Play Games

JZ26 樹的子結構 描述 輸入兩棵二叉樹A,B,判斷B是不是A的子結構。(我們約定空樹不是任意一個樹的子結構) 假如給定A為{8,8,7,9,2,#,#,#,#,4,7},B為{8,9,2},2個樹的結構如下,可以看出B是A的子結構 題解1 深度遍歷 思路 既然是要找到A樹中是否有B樹這樣子樹,如 ...


JZ26 樹的子結構

描述

輸入兩棵二叉樹A,B,判斷B是不是A的子結構。(我們約定空樹不是任意一個樹的子結構)
假如給定A為{8,8,7,9,2,#,#,#,#,4,7},B為{8,9,2},2個樹的結構如下,可以看出B是A的子結構

題解1 深度遍歷

思路

既然是要找到A樹中是否有B樹這樣子樹,如果是有子樹肯定是要遍歷這個子樹和B樹,將兩個的節點一一比較,但是這樣的子樹不一定就是A樹根節點開始的,所以我們還要先找到子樹可能出現的位置。
既然是可能的位置,那我們可以對A樹的每個節點前序遞歸遍歷,尋找是否有這樣的子樹,而尋找是否有子樹的時候,我們就將A樹與B樹同步前序遍歷,依次比較節點值。

具體做法:
step 1:因為空樹不是任何樹的子樹,所以要先判斷B樹是否為空樹。
step 2:當A樹為空節點,但是B樹還有節點的時候,不為子樹,但是A樹不為空節點,B樹為空節點時可以是子樹。
step 3:每次遞歸比較A樹從當前節點開始,是否與B樹完全一致,同步前序遍歷。
step 4:A樹自己再前序遍歷進入子節點,當作子樹起點再與B樹同步遍歷。
step 5:以上情況任意只要有一種即可。

代碼

public class Solution {
    public boolean HasSubtree(TreeNode root1, TreeNode root2) {
        if (root2 == null) return false;
        //一個節點為空 一節點不為空
        if (root1 == null) return false;

        boolean flag1 = recursion(root1, root2);

        boolean flag2 = HasSubtree(root1.left, root2);

        boolean flag3 = HasSubtree(root1.right, root2);
        return flag1 || flag2 || flag3;
    }

    // 判斷是否有相等的根節點
    public boolean recursion(TreeNode root1, TreeNode root2) {
        //一個節點為空 一節點不為空
        if (root1 == null && root2 != null) return false;

        if (root1 == null || root2 == null) return true;

        if (root1.val != root2.val) return false;

        return recursion(root1.left, root2.left) && recursion(root1.right, root2.right);
    }
}

題解2 廣度遍歷

思路

首先對於A樹層次遍歷每一個節點,遇到一個與B樹根節點相同的節點,我們就開始同步層次遍歷比較以這個節點為根的樹中是否出現了B樹的全部節點。因為我們只考慮B樹的所有節點是否在A樹中全部出現,那我們就以B樹為基,再進行一次層次遍歷,A樹從那個節點開始跟隨B樹一致進行層次遍歷就行了,比較對應的每個點是否相同,或者B樹是否有超出A樹沒有的節點。

具體做法:

step 1:先判斷空樹,空樹不為子結構。
step 2:利用隊列輔助,層次遍歷第一棵樹,每次檢查遍歷到的節點是否和第二棵樹的根節點相同。
step 3:若是相同,可以以該節點為子樹根節點,再次藉助隊列輔助,同步層次遍歷這個子樹與第二棵樹,這個時候以第二棵樹為基,只要找到第二棵樹的全部節點,就算找到了子結構。

代碼

package mid.JZ26樹的子結構;
import java.util.LinkedList;

class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}

public class Solution {
    public boolean HasSubtree(TreeNode root1, TreeNode root2) {
        if (root2 == null) return false;
        //一個節點為空 一節點不為空
        if (root1 == null) return false;
        LinkedList<TreeNode> q = new LinkedList<>();
        q.offer(root1);

        while (!q.isEmpty()) {
            TreeNode node = q.poll();
            if (node.val == root2.val) {
                if (helper(node, root2)) {
                    return true;
                }
            }

            if (node.left != null) q.offer(node.left);
            if (node.right != null) q.offer(node.right);
        }
        return false;
    }

    public boolean helper(TreeNode root1, TreeNode root2) {
        LinkedList<TreeNode> q1 = new LinkedList<>();
        LinkedList<TreeNode> q2 = new LinkedList<>();
        q1.offer(root1);
        q2.offer(root2);

        while (!q2.isEmpty()) {
            TreeNode node1 = q1.poll();
            TreeNode node2 = q2.poll();
            //樹1為空或者二者不相等
            if (node1 == null || node1.val != node2.val)
                return false;
            //樹2還有左子樹
            if (node2.left != null) {
                //子樹入隊
                q1.offer(node1.left);
                q2.offer(node2.left);
            }
            //樹2還有右子樹
            if (node2.right != null) {
                //子樹入隊
                q1.offer(node1.right);
                q2.offer(node2.right);
            }
        }
        return true;
    }

}


// 深度遍歷查詢
/*public class Solution {
    public boolean HasSubtree(TreeNode root1, TreeNode root2) {
        if (root2 == null) return false;
        //一個節點為空 一節點不為空
        if (root1 == null) return false;

        boolean flag1 = recursion(root1, root2);

        boolean flag2 = HasSubtree(root1.left, root2);

        boolean flag3 = HasSubtree(root1.right, root2);
        return flag1 || flag2 || flag3;
    }

    // 判斷是否有相等的根節點
    public boolean recursion(TreeNode root1, TreeNode root2) {
        //一個節點為空 一節點不為空
        if (root1 == null && root2 != null) return false;

        if (root1 == null || root2 == null) return true;

        if (root1.val != root2.val) return false;

        return recursion(root1.left, root2.left) && recursion(root1.right, root2.right);
    }
}*/

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 好家伙, xdm,密碼驗證忘寫了,哈哈 bug展示: 1.登陸沒有密碼驗證 主要體現為,亂輸也能登進去 (小問題) 要是這麼上線估計直接寄了 分析一波密碼校驗怎麼做: 前端輸完用戶名密碼之後,將數據發送到後端處理 後端要做以下幾件事 ①先確認這個用戶名已註冊 ②我們拿著這個用戶名去資料庫中找對應的數 ...
  • 說明: 本文基於Spring-Framework 5.1.x版本講解 概述 說起生命周期, 很多開源框架、中間件的組件都有這個詞,其實就是指組件從創建到銷毀的過程。 那這裡講Spring Bean的生命周期,並不是講Bean是如何創建的, 而是想講下Bean從實例化到銷毀,Spring框架在Bean ...
  • 1、Durid 1.1 簡介 Java程式很大一部分要操作資料庫,為了提高性能操作資料庫的時候,又不得不使用資料庫連接池。 Druid 是阿裡巴巴開源平臺上一個資料庫連接池實現,結合了 C3P0、DBCP 等 DB 池的優點,同時加入了日誌監控。 Druid 可以很好的監控 DB 池連接和 SQL ...
  • 1、參考文獻說明 參考博客:https://www.cnblogs.com/dy12138/articles/16799941.html Vmware Workstation pro 17 安裝會比較簡單,基本上點下一步就行了。 新功能介紹和破解碼請見:https://www.ghxi.com/vm ...
  • 鎖概述 在電腦科學中,鎖是在執行多線程時用於強行限制資源訪問的同步機制,即用於在併發控制中保證對互斥要求的滿足。 鎖相關概念 鎖開銷:完成一個鎖可能額外耗費的資源,比如一個周期所需要的時間,記憶體空間。 鎖競爭:一個線程或進程,要獲取另一個線程或進程所持有的鎖,邊會發生鎖競爭。鎖粒度越小,競爭的可能 ...
  • 原文鏈接: JWT詳解:https://blog.csdn.net/weixin_45070175/article/details/118559272 1、什麼是JWT 通俗地說,JWT的本質就是一個字元串,它是將用戶信息保存到一個Json字元串中,然後進行編碼後得到一個JWT token,並且這個 ...
  • Hello,大家好,我是阿粉,對接文檔是每個開發人員不可避免都要寫的,友好的文檔可以大大的提升工作效率。 阿粉最近將項目的文檔基於 Gitbook 和 Gitlab 的 Webhook 功能的在內網部署了一套實時的,使用起來特方便了。跟著阿粉的步驟,教你部署自己的文檔服務。 步驟 安裝 Node 和 ...
  • 序列的修改、散列和切片 from array import array import reprlib, math, numbers from functools import reduce from operator import xor from itertools import chain # ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...