【代碼隨想錄刷題】Day20 二叉樹06

在這里插入圖片描述

文章目錄

  • 1.【654】最大二叉樹
    • 1.1 題目描述
    • 1.2 解題思路
    • 1.3 java代碼實現
    • 1.4 總結
  • 2.【617】合并二叉樹
    • 2.1 題目描述
    • 2.2 解題思路
    • 2.3 java代碼實現
  • 3.【700】二叉搜索樹中的搜索
    • 3.1 題目描述
    • 3.2 解題思路
    • 3.3 java代碼實現
  • 4.【98】驗證二叉搜索樹
    • 4.1 題目描述
    • 4.2 解題思路
    • 4.3 java代碼實現

【654】最大二叉樹
【617】合并二叉樹
【700】二叉搜索樹中的搜索
【98】驗證二叉搜索樹

1.【654】最大二叉樹

【654】最大二叉樹

1.1 題目描述

給定一個不重復的整數數組 nums 。 最大二叉樹 可以用下面的算法從 nums 遞歸地構建:

  • 1.創建一個根節點,其值為 nums 中的最大值。
  • 2.遞歸地在最大值 左邊 的 子數組前綴上 構建左子樹。
  • 3.遞歸地在最大值 右邊 的 子數組后綴上 構建右子樹。

返回 nums 構建的 最大二叉樹 。
在這里插入圖片描述
解釋: 遞歸調用如下所示:

  • [3,2,1,6,0,5] 中的最大值是 6 ,左邊部分是 [3,2,1] ,右邊部分是 [0,5] 。
    • [3,2,1] 中的最大值是 3 ,左邊部分是 [] ,右邊部分是 [2,1] 。
      • 空數組,無子節點。
      • [2,1] 中的最大值是 2 ,左邊部分是 [] ,右邊部分是 [1] 。
        • 空數組,無子節點。
        • 只有一個元素,所以子節點是一個值為 1 的節點。
    • [0,5] 中的最大值是 5 ,左邊部分是 [0] ,右邊部分是 [] 。
      • 只有一個元素,所以子節點是一個值為 0 的節點。
      • 空數組,無子節點。
        在這里插入圖片描述
        提示:
  • 1 <= nums.length <= 1000
  • 0 <= nums[i] <= 1000
  • nums 中的所有整數 互不相同

1.2 解題思路

最大二叉樹的構建過程如下:

請添加圖片描述
構造樹一般采用的是前序遍歷,因為先構造根節點,然后遞歸構造左子樹和右子樹。

遞歸三部曲

    1. 確定遞歸函數的參數和返回值

參數:存放元素的數組

返回值:返回該數組構造的二叉樹的頭結點

  public TreeNode travesal(int[] nums,int leftIndex,int rightIndex)
    1. 確定終止條件

題目中說了輸入的數組大小一定是大于等于1的,所以我們不用考慮小于1的情況,那么當遞歸遍歷的時候,如果傳入的數組大小為1,說明遍歷到了葉子節點了。

那么應該定義一個新的節點,并把這個數組的數值賦給新的節點,然后返回這個節點。 這表示一個數組大小是1的時候,構造了一個新的節點,并返回。

 		//沒有元素if (rightIndex-leftIndex<1){return null;}//只有一個元素if (rightIndex-leftIndex==1){return new TreeNode(nums[leftIndex]);}
    1. 確定單層遞歸的邏輯

這里又要分為三步:

1.先要找到數組中最大的值和對應的下標, 最大的值構造根節點,下標用來下一步分割數組

		//最大值所在位置int maxIndex=leftIndex;//最大值int maxVal=nums[maxIndex];//找最大值for (int i = leftIndex+1; i < rightIndex; i++) {if (nums[i]>maxVal){maxVal=nums[i];maxIndex=i;}}TreeNode root=new TreeNode(maxVal);

2.最大值所在的下標左區間 構造左子樹
3.最大值所在的下標右區間 構造右子樹

 		//根據maxIndex劃分左右子樹root.left=travesal(nums,leftIndex,maxIndex);root.right=travesal(nums,maxIndex+1,rightIndex);

1.3 java代碼實現

class Solution {public TreeNode constructMaximumBinaryTree(int[] nums) {return travesal(nums,0,nums.length);}/*** 先找出最大元素,即根節點* 用最大元素來劃分左右子樹區間*/public TreeNode travesal(int[] nums,int leftIndex,int rightIndex){//沒有元素if (rightIndex-leftIndex<1){return null;}//只有一個元素if (rightIndex-leftIndex==1){return new TreeNode(nums[leftIndex]);}//最大值所在位置int maxIndex=leftIndex;//最大值int maxVal=nums[maxIndex];//找最大值for (int i = leftIndex+1; i < rightIndex; i++) {if (nums[i]>maxVal){maxVal=nums[i];maxIndex=i;}}TreeNode root=new TreeNode(maxVal);//根據maxIndex劃分左右子樹root.left=travesal(nums,leftIndex,maxIndex);root.right=travesal(nums,maxIndex+1,rightIndex);return root;}
}

1.4 總結

此題與【106】從中序與后序遍歷序列構造二叉樹解題思路是一樣的。此題的詳細解題思路請看【代碼隨想錄刷題】Day18 二叉樹05。

注意類似用數組構造二叉樹的題目,每次分隔盡量不要定義新的數組,而是通過下標索引直接在原數組上操作,這樣可以節約時間和空間上的開銷。

遞歸函數前面加if的情況:一般情況來說:如果讓空節點(空指針)進入遞歸,就不加if,如果不讓空節點進入遞歸,就加if限制一下, 終止條件也會相應的調整。其實這就是不同代碼風格的實現。

2.【617】合并二叉樹

【617】合并二叉樹

2.1 題目描述

給你兩棵二叉樹: root1 和 root2 。

想象一下,當你將其中一棵覆蓋到另一棵之上時,兩棵樹上的一些節點將會重疊(而另一些不會)。你需要將這兩棵樹合并成一棵新二叉樹。合并的規則是:如果兩個節點重疊,那么將這兩個節點的值相加作為合并后節點的新值;否則,不為 null 的節點將直接作為新二叉樹的節點。

返回合并后的二叉樹。

注意: 合并過程必須從兩個樹的根節點開始。

在這里插入圖片描述
提示:

  • 兩棵樹中的節點數目在范圍 [0, 2000] 內
  • -104 <= Node.val <= 104

2.2 解題思路

本題使用前序遍歷。

遞歸三部曲

    1. 確定遞歸函數的參數和返回值

首先要合入兩個二叉樹,那么參數至少是要傳入兩個二叉樹的根節點,返回值就是合并之后二叉樹的根節點。

public TreeNode mergeTrees(TreeNode root1, TreeNode root2)
    1. 確定終止條件

因為是傳入了兩個樹,那么就有兩個樹遍歷的節點t1 和 t2,如果t1 == NULL 了,兩個樹合并就應該是 t2 了(如果t2也為NULL也無所謂,合并之后就是NULL)。

反過來如果t2 == NULL,那么兩個數合并就是t1(如果t1也為NULL也無所謂,合并之后就是NULL)。

		if(root1==null){return root2;}if (root2==null){return root1;}
    1. 確定單層遞歸的邏輯

我們重復利用一下t1這個樹,t1就是合并之后樹的根節點(就是修改了原來樹的結構)。那么單層遞歸中,就要把兩棵樹的元素加到一起。

 root1.val+= root2.val;

接下來t1 的左子樹是:合并 t1左子樹 t2左子樹之后的左子樹。

t1 的右子樹:是 合并 t1右子樹 t2右子樹之后的右子樹。

最終t1就是合并之后的根節點。

		root1.left=mergeTrees(root1.left,root2.left);root1.right=mergeTrees(root1.right,root2.right);return root1;

2.3 java代碼實現

遞歸

class Solution {public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {if(root1==null){return root2;}if (root2==null){return root1;}root1.val+= root2.val;root1.left=mergeTrees(root1.left,root2.left);root1.right=mergeTrees(root1.right,root2.right);return root1;}
}

迭代

class Solution {public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {//使用隊列迭代if(root1==null){return root2;}if (root2==null){return root1;}Queue<TreeNode> queue=new LinkedList<>();queue.offer(root1);queue.offer(root2);while (!queue.isEmpty()){TreeNode node1=queue.poll();TreeNode node2=queue.poll();//此時兩個節點一定不為空,值val相加node1.val+=node2.val;//如果兩棵樹左節點不為空,加入隊列if (node1.left!=null && node2.left!=null){queue.offer(node1.left);queue.offer(node2.left);}//如果兩棵樹右節點不為空,加入隊列if (node1.right!=null && node2.right!=null){queue.offer(node1.right);queue.offer(node2.right);}//若node1的左節點為空,直接賦值if (node1.left==null && node2.left!=null){node1.left=node2.left;}//若node1的右節點為空,直接賦值if (node1.right==null && node2.right!=null){node1.right=node2.right;}}return root1;}
}

3.【700】二叉搜索樹中的搜索

【700】二叉搜索樹中的搜索

3.1 題目描述

給定二叉搜索樹(BST)的根節點 root 和一個整數值 val。

你需要在 BST 中找到節點值等于 val 的節點。 返回以該節點為根的子樹。 如果節點不存在,則返回 null 。
在這里插入圖片描述
提示:

  • 樹中節點數在 [1, 5000] 范圍內
  • 1 <= Node.val <= 107
  • root 是二叉搜索樹
  • 1 <= val <= 107

3.2 解題思路

首先要知道什么是二叉搜索樹。

二叉搜索樹是一個有序樹:

  • 若它的左子樹不空,則左子樹上所有結點的值均小于它的根結點的值;
  • 若它的右子樹不空,則右子樹上所有結點的值均大于它的根結點的值;
  • 它的左、右子樹也分別為二叉搜索樹

這就決定了,二叉搜索樹,遞歸遍歷和迭代遍歷和普通二叉樹都不一樣。

遞歸法

    1. 確定遞歸函數的參數和返回值

遞歸函數的參數傳入的就是根節點和要搜索的數值,返回的就是以這個搜索數值所在的節點。

public TreeNode searchBST(TreeNode root, int val)
    1. 確定終止條件

如果root為空,或者找到這個數值了,就返回root節點。

if (root==null || root.val==val){return root;}
    1. 確定單層遞歸的邏輯

看看二叉搜索樹的單層遞歸邏輯有何不同。

因為二叉搜索樹的節點是有序的,所以可以有方向的去搜索。

如果root->val > val,搜索左子樹,如果root->val < val,就搜索右子樹,最后如果都沒有搜索到,就返回NULL。

 		if (val< root.val){return searchBST(root.left,val);}else {return searchBST(root.right,val);}

迭代法

一提到二叉樹遍歷的迭代法,可能立刻想起使用棧來模擬深度遍歷,使用隊列來模擬廣度遍歷。

對于二叉搜索樹可就不一樣了,因為二叉搜索樹的特殊性,也就是節點的有序性,可以不使用輔助棧或者隊列就可以寫出迭代法。

對于一般二叉樹,遞歸過程中還有回溯的過程,例如走一個左方向的分支走到頭了,那么要調頭,在走右分支。

而對于二叉搜索樹,不需要回溯的過程,因為節點的有序性就幫我們確定了搜索的方向。

例如要搜索元素為3的節點,我們不需要搜索其他節點,也不需要做回溯,查找的路徑已經規劃好了。
請添加圖片描述

3.3 java代碼實現

遞歸

class Solution {public TreeNode searchBST(TreeNode root, int val) {if (root==null || root.val==val){return root;}if (val< root.val){return searchBST(root.left,val);}else {return searchBST(root.right,val);}}
}

迭代

class Solution {public TreeNode searchBST(TreeNode root, int val) {//迭代while (root != null)if (val < root.val) root = root.left;else if (val > root.val) root = root.right;else return root;return null;}
}

4.【98】驗證二叉搜索樹

【98】驗證二叉搜索樹

4.1 題目描述

給你一個二叉樹的根節點 root ,判斷其是否是一個有效的二叉搜索樹。

有效 二叉搜索樹定義如下:

  • 節點的左子樹只包含 小于 當前節點的數。
  • 節點的右子樹只包含 大于 當前節點的數。
  • 所有左子樹和右子樹自身必須也是二叉搜索樹。

在這里插入圖片描述
提示:

  • 樹中節點數目范圍在[1, 104] 內
  • -231 <= Node.val <= 231 - 1

4.2 解題思路

劃重點啦啦啦啦!!!!!!

要知道中序遍歷下,輸出的二叉搜索樹節點的數值是有序序列。

有了這個特性,驗證二叉搜索樹,就相當于變成了判斷一個序列是不是遞增的了。

遞歸法:
可以遞歸中序遍歷將二叉搜索樹轉變成一個數組,然后只要比較一下,這個數組是否是有序的,注意二叉搜索樹中不能有重復元素

陷阱!!!
陷阱!!!
陷阱!!!

不能單純的比較左節點小于中間節點,右節點大于中間節點就完事了。
我們要比較的是 左子樹所有節點小于根節點右子樹所有節點大于根節點

比如下圖中這種情況:

在這里插入圖片描述
節點15大于左節點10,2,小于右節點17,但是右子樹里出現了一個9這就不符合二叉搜索樹了。

遞歸三部曲:

    1. 確定遞歸函數,返回值以及參數
      用題目中給出的即可
    1. 確定終止條件

如果是空節點 是不是二叉搜索樹呢?是的,二叉搜索樹也可以為空!

		if (root==null){return true;}
    1. 確定單層遞歸的邏輯

中序遍歷,一直更新max,一旦發現max >= root.val,就返回false,注意元素相同時候也要返回false。

		//左boolean left=isValidBST(root.left);if (!left){return false;}//根if (max!=null && root.val<=max.val){return false;}max=root;//右boolean right=isValidBST(root.right);return right;

迭代法:

可以用迭代法模擬二叉樹中序遍歷,那么此題將迭代法中序遍歷稍加改動就可以了。

4.3 java代碼實現

遞歸

  • 先判斷左子樹,若左子樹有一個節點不是小于根節點的值,直接返回false
  • 若左子樹為true,再判斷右子樹
  • 若右子樹為true,整個遞歸直接返回true;若右子樹為false,整個遞歸直接返回false。
class Solution {TreeNode max;public boolean isValidBST(TreeNode root) {//遞歸if (root==null){return true;}//左boolean left=isValidBST(root.left);if (!left){return false;}//根if (max!=null && root.val<=max.val){return false;}max=root;//右boolean right=isValidBST(root.right);return right;}
}

迭代

class Solution {public boolean isValidBST(TreeNode root) {//迭代if (root==null){return true;}Stack<TreeNode> stack=new Stack<>();TreeNode pre=null;//前一個節點while (root!=null || !stack.isEmpty()){while (root!=null){stack.push(root);root=root.left;//左}//根TreeNode pop=stack.pop();if (pre!=null && pop.val<=pre.val){return false;}pre=pop;//右root=pop.right;}return true;}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/207999.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/207999.shtml
英文地址,請注明出處:http://en.pswp.cn/news/207999.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

盤點11月Sui生態發展,了解Sui的近期成長歷程!

11月是Web3的“回暖期”&#xff0c;行業持續展現增長趨勢。Sui緊隨行業腳步&#xff0c;開展了一系列生態活動。其中歷時一個多月的Quest 3游戲活動順利結束并公布獎勵&#xff0c;在多地區成功舉辦Move和Sui生態黑客松&交流會&#xff0c;還有針對中文社區開發者教育的星…

MQTT協議對比QUIC網絡性能測試模擬弱網測試

MQTT正常外網壓測數據---時延diff/ms如下圖&#xff1a; MQTT弱網外網壓測數據 QUIC正常外網壓測數據 QUIC弱網外網壓測數據 結論&#xff1a; 在弱網情況下&#xff0c;MQTT和QUIC&#xff08;Quick UDP Internet Connections&#xff09;這兩種協議的網絡性能表現也會有…

Axure原型圖表組件庫,數據可視化元件(Axure9大屏組件)

針對Axure制作的大屏圖表元件庫&#xff0c;幫助產品經理更高效地制作高保真圖表原型&#xff0c;是產品經理必備元件工具。現分享完整的組件庫&#xff0c;大家一起學習。 本組件庫的圖表模塊&#xff0c;已包含所有常用的圖表&#xff0c;以下為部分組件截圖示意。文末可下載…

頁面初始化后,需要滾動到某個元素的位置,但是該元素尚未渲染完成。

vue方式 <template><div class"doc"><!-- 判斷是否還在渲染期間 --><div class"fixed" v-show"loading">頁面仍在渲染中&#xff0c;請稍后</div><div class"green" v-show"!loading">…

TA-Lib學習研究筆記(九)——Pattern Recognition (2)

TA-Lib學習研究筆記&#xff08;九&#xff09;——Pattern Recognition &#xff08;2&#xff09; 形態識別的函數的應用&#xff0c;通過使用A股實際的數據&#xff0c;驗證形態識別函數&#xff0c;用K線顯示出現標志的形態走勢&#xff0c;由于入口參數基本上是open, hig…

反向傳播算法

反向傳播算法的數學解釋 反向傳播算法是深度學習中用于訓練神經網絡的核心算法。它通過計算損失函數相對于網絡權重的梯度來更新權重&#xff0c;從而最小化損失。 反向傳播的基本原理 反向傳播算法基于鏈式法則&#xff0c;它按層反向傳遞誤差&#xff0c;從輸出層開始&…

寒冬不再寒冷:氣膜體育館如何打造溫馨運動天地

取暖季即將來臨&#xff0c;隨著氣溫逐漸下降&#xff0c;人們在寒冷的冬季里如何保持運動熱情和身體的健康成為了一項挑戰。而在這個時候&#xff0c;氣膜體育館成為了運動愛好者們的理想場所&#xff0c;提供如春般溫暖舒適的運動環境。那么&#xff0c;讓我們一起揭秘氣膜體…

2024年SEO策略:如何優化您的知識庫?

如今很多人在遇到問題時都會求助于谷歌。谷歌已經成為提供解決方案不可或缺的工具。作為全球搜索引擎的巨頭&#xff0c;擁有大量用戶流量。這就是為什么確保您的產品和服務在谷歌搜索結果中排名靠前是至關重要的&#xff0c;如果您想獲得更多的客戶&#xff0c;SEO是一個非常關…

Filed II 繪制超聲 3D/2D 點擴散函數

點擴散函數可以較好地描述超聲對成像目標分辨能力,利用 filed II 仿真工具實現點擴算函數 PSF 的 3D 和 2D 繪制。 定義換能器基本參數 f0=5e6; % Transducer center frequency [Hz] fs=100e6; % Sampling frequency [Hz] c=1540; % Speed of sound [m/s] width=0.15/1000

<Linux> 文件系統

目錄 前言&#xff1a; 一、 磁盤 &#xff08;一&#xff09;磁盤的物理結構 &#xff08;二&#xff09;磁盤的物理存儲結構 1. 數據存儲 2. 存儲結構 二、磁盤的邏輯抽象 三、磁盤信息 &#xff08;一&#xff09;具體結構 &#xff08;二&#xff09;重新認識目錄…

SOLIDWORKS Flow Simulation電子機箱散熱

這一次我們來聊聊電子冷卻問題&#xff0c;以這個機箱散熱問題為例&#xff0c;我們一般的散熱設計要求是CPU不能超過80℃&#xff0c;北橋芯片溫度不能超過85℃&#xff0c;南橋芯片不超過95℃。在實際情況下芯片內部的各處溫度是不一樣&#xff0c;面對與芯片級別的散熱分析我…

mysql中MDL(元數據鎖)的長事務讀寫阻塞如何解決

MDL&#xff0c;即元數據鎖是什么&#xff0c;我們已經介紹過了 那其存在的長事務讀寫阻塞問題&#xff0c;一般是怎么解決的呢&#xff0c;主要有兩種解決方法。 online ddl MySQL5.6開始&#xff0c;推出一項新功能Online DDL&#xff0c;在ALTER或者CREATE INDEX等語句后添…

【教學類-35-05】17號的學號字帖(A4豎版1份)

作品展示&#xff1a; 背景需求&#xff1a; 大四班17號男孩目前無法自主數學數字。他表示自己能夠認識數字&#xff0c;但不會寫。 保育老師說&#xff1a;我曾經教過他&#xff0c;抓著手示范的。但是他記不住。家里估計也不練習的。年齡還沒到&#xff0c;下學期再看看能不…

有限空間作業中毒窒息事故頻發,漢威科技創新方案護航

工貿企業有限空間是我國重大事故多發頻發的重點領域之一&#xff0c;安全問題形勢嚴峻。 有限空間是指封閉或者部分封閉、未被設計為固定工作場所&#xff0c;人員可以進入&#xff0c;通風不良&#xff0c;易造成有毒有害物質、易燃易爆氣體積聚或者氧含量不足的空間&#xf…

消息中間件基本概念

基本概念 消息隊列三個場景&#xff1a;異步&#xff0c;削峰&#xff0c;解耦 異步&#xff1a;將整個流程進行異步發送&#xff0c;也就是說本來順序執行的程序化流程&#xff0c;異步后可以同時進行操作&#xff0c;互不影響&#xff0c;但保持最終結果一致性&#xff1b;…

ChatGPT顛覆性地改變了個性化學習

開發者歡呼,ChatGPT開啟了教育的新時代教育者和學生都將從革命性的技術中受益ChatGPT是由OpenAI開發的強大的語言模型,它在個性化學習領域取得了重大突破。這一新的發展有望徹底改變教育的方式,使其更加定制化、有趣和有效。 開發者和教育者的重大新聞 這一消息對于一直努…

excel做預測的方法集合

一. LINEST函數 首先&#xff0c;一元線性回歸的方程&#xff1a; y a bx 相應的&#xff0c;多元線性回歸方程式&#xff1a; y a b1x1 b2x2 … bnxn 這里&#xff1a; y - 因變量即預測值x - 自變量a - 截距b - 斜率 LINEST的可以返回回歸方程的 截距(a) 和 斜…

jsp使用 分頁專用工具

分頁器&#xff0c;根據過來的參數計算當著頁應當從哪一條記錄開始顯示&#xff0c;并且顯示到哪。 PageUtils [pageSize5, currIndex1, totalCount166, totalPage34, startPosition0] PageUtils [pageSize5, currIndex5, totalCount166, totalPage34, startPosition20] PageUt…

5.10 Windows驅動開發:摘除InlineHook內核鉤子

在筆者上一篇文章《內核層InlineHook掛鉤函數》中介紹了通過替換函數頭部代碼的方式實現Hook掛鉤&#xff0c;對于ARK工具來說實現掃描與摘除InlineHook鉤子也是最基本的功能&#xff0c;此類功能的實現一般可在應用層進行&#xff0c;而驅動層只需要保留一個讀寫字節的函數即可…

得帆云助力容百科技構建CRM系統,實現LTC全流程管理

寧波容百新能源科技股份有限公司 寧波容百新能源科技股份有限公司&#xff08;以下簡稱“容百科技”&#xff09;于2014年9月建立&#xff0c;是高科技新能源材料行業的跨國型集團公司。專業從事鋰電池正極材料的研發、生產和銷售&#xff0c;于2019年登陸上交所科創板&#x…