驗證二叉搜索樹[中等]

優質博文:IT-BLOG-CN

一、題目

給你一個二叉樹的根節點root,判斷其是否是一個有效的二叉搜索樹。有效 二叉搜索樹定義如下:
【1】節點的左子樹只包含 小于 當前節點的數。
【2】節點的右子樹只包含 大于 當前節點的數。
【3】所有左子樹和右子樹自身必須也是二叉搜索樹。

示例 1:

輸入:root = [2,1,3]
輸出:true

示例 2:

輸入:root = [5,1,4,null,null,3,6]
輸出:false
解釋:根節點的值是5,但是右子節點的值是4

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

二、代碼

【1】遞歸: 要解決這道題首先我們要了解二叉搜索樹有什么性質可以給我們利用,由題目給出的信息我們可以知道:如果該二叉樹的左子樹不為空,則左子樹上所有節點的值均小于它的根節點的值; 若它的右子樹不空,則右子樹上所有節點的值均大于它的根節點的值;它的左右子樹也為二叉搜索樹。

這啟示我們設計一個遞歸函數helper(root, lower, upper)來遞歸判斷,函數表示考慮以root為根的子樹,判斷子樹中所有節點的值是否都在(l,r)的范圍內(注意是開區間)。如果root節點的值val不在(l,r)的范圍內說明不滿足條件直接返回,否則我們要繼續遞歸調用檢查它的左右子樹是否滿足,如果都滿足才說明這是一棵二叉搜索樹。

那么根據二叉搜索樹的性質,在遞歸調用左子樹時,我們需要把上界upper改為root.val,即調用helper(root.left, lower, root.val),因為左子樹里所有節點的值均小于它的根節點的值。同理遞歸調用右子樹時,我們需要把下界lower改為root.val,即調用helper(root.right, root.val, upper)

函數遞歸調用的入口為helper(root, -inf, +inf)inf表示一個無窮大的值。

class Solution {public boolean isValidBST(TreeNode root) {return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);}public boolean isValidBST(TreeNode node, long lower, long upper) {if (node == null) {return true;}if (node.val <= lower || node.val >= upper) {return false;}return isValidBST(node.left, lower, node.val) && isValidBST(node.right, node.val, upper);}
}

時間復雜度: O(n),其中n為二叉樹的節點個數。在遞歸調用的時候二叉樹的每個節點最多被訪問一次,因此時間復雜度為O(n)
空間復雜度: O(n),其中n為二叉樹的節點個數。遞歸函數在遞歸過程中需要為每一層遞歸函數分配棧空間,所以這里需要額外的空間且該空間取決于遞歸的深度,即二叉樹的高度。最壞情況下二叉樹為一條鏈,樹的高度為n,遞歸最深達到n層,故最壞情況下空間復雜度為O(n)

【2】中序遍歷: 基于方法一中提及的性質,我們可以進一步知道二叉搜索樹「中序遍歷」得到的值構成的序列一定是升序的,這啟示我們在中序遍歷的時候實時檢查當前節點的值是否大于前一個中序遍歷到的節點的值即可。如果均大于說明這個序列是升序的,整棵樹是二叉搜索樹,否則不是,下面的代碼我們使用棧來模擬中序遍歷的過程。

可能有讀者不知道中序遍歷是什么,我們這里簡單提及。中序遍歷是二叉樹的一種遍歷方式,它先遍歷左子樹,再遍歷根節點,最后遍歷右子樹。而我們二叉搜索樹保證了左子樹的節點的值均小于根節點的值,根節點的值均小于右子樹的值,因此中序遍歷以后得到的序列一定是升序序列。

class Solution {public boolean isValidBST(TreeNode root) {Deque<TreeNode> stack = new LinkedList<TreeNode>();double inorder = -Double.MAX_VALUE;while (!stack.isEmpty() || root != null) {while (root != null) {stack.push(root);root = root.left;}root = stack.pop();// 如果中序遍歷得到的節點的值小于等于前一個 inorder,說明不是二叉搜索樹if (root.val <= inorder) {return false;}inorder = root.val;root = root.right;}return true;}
}

時間復雜度: O(n),其中n為二叉樹的節點個數。二叉樹的每個節點最多被訪問一次,因此時間復雜度為O(n)
空間復雜度: O(n),其中n為二叉樹的節點個數。棧最多存儲n個節點,因此需要額外的O(n)的空間。

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

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

相關文章

Leetcode 40 組合總和 II

題意理解&#xff1a; 每個數字在每個組合中只能使用 一次 數字可以重復——>難點&#xff08;如何去重&#xff09; 每個組合和target 求組合&#xff0c;對合限制&#xff0c;考慮回溯的方法。——將其抽象為樹結構。 樹的寬度——分支大小 樹的深度——最…

Spring IoC和DI

目錄 一. Spring是什么 IoC DI 二. IoC&DI的使用 IoC 1.Controller&#xff08;控制器存儲&#xff09; 2.Service&#xff08;服務存儲&#xff09; 3.Repository&#xff08;倉庫存儲&#xff09; 4.Componemt&#xff08;組件存儲&#xff09; 5.Configuratio…

解決Could not establish connection to : XHR failed

解決Could not establish connection to : XHR failed 問題描述 用vscode用遠程連接服務器時總報上面的錯誤&#xff0c;用xshell和Xftp和vscode終端都可以連上&#xff0c;但是用vscode的ssh連接缺總報錯&#xff0c;導致無法連接服務器進行代碼調試 一、原因 原因可能是在…

【MATLAB】 數據、矩陣、行、列翻轉

1.MATLAB函數fliplr 用法&#xff1a;fliplr(X) 功能&#xff1a;matlab中的fliplr函數實現矩陣的左右翻轉。 fliplr(X)使矩陣X沿垂直軸左右翻轉。 相關函數&#xff1a;flipud函數可以實現矩陣的上下翻轉。 備注&#xff1a;matlab中提供了許多對矩陣操作的函數&#xff0c;可…

Go json 差異比較 json-diff(RFC6902)

Go json 差異比較 json-diff(RFC 6902) 畢業設計中過程中為了比較矢量圖的差異而依據 RFC 6902 編寫的一個包&#xff0c;現已開源&#xff1a; Json-diff 使用 go get -u github.com/520MianXiangDuiXiang520/json-diff序列化與反序列化 與官方 json 包的序列化和反序列化不…

后端開發面試題

這是一波今年7月份的大廠面試題&#xff0c;分享下&#xff5e;&#xff5e; Mybatis三級緩存 Mybatis懶加載 分布式事務 transaction gradle和maven區別 抽象類、多態 Springboot啟動 ConcurrentHashMap 樂觀鎖、悲觀鎖 docker k8s常用命令 電商業務從什么維度分庫分…

AcWing 95. 費解的開關(遞推)

題目鏈接 活動 - AcWing 本活動組織刷《算法競賽進階指南》&#xff0c;系統學習各種編程算法。主要面向有一定編程基礎的同學。https://www.acwing.com/problem/content/97/ 題解 只要第一行開關的狀態確定&#xff0c;則所有開關的狀態都可以被推出來。第一行開關總共有種操…

jemeter,同一線程組內,調用cookie實現接口關聯

取cookie方式參考上一篇&#xff1a;jemeter&#xff0c;取“臨時重定向的登錄接口”響應頭中的cookie-CSDN博客 元件結構 登錄后要執行的接口為“api/get_event_list/”&#xff0c;在該HTTP請求下創建HTTP信息頭管理器&#xff0c;配置如下&#xff1a; 執行測試后&#xff0…

【ensp實踐】eNSP實戰篇(4)用eNSP實驗來認識什么是OSPF及OSPF配置?

OSPF目錄 寫在前面涉及知識一、什么是OSPF&#xff1f;二、OSPF特性&#xff08;優缺點&#xff09;2.1 OSPF優點2.2 OSPF缺點 三、OSPF實驗3.1 打開ensp&#xff0c;添加設備3.2 建立連線3.3 配置及ospf命令【核心】3.3.1 配置PC機3.3.2 設置命令 3.4 驗證效果3.4.1、驗證OSPF…

Spring IoC如何存取Bean對象

小王學習錄 IoC(Inversion of Control)1. 什么是IoC2. 什么是Spring IoC3. 什么是DI4. Spring IoC的作用 存儲Bean對象1. 創建Bean2. 將Bean注冊到Spring中. 取Bean對象.1. 獲取Spring上下文信息使用ApplicationContext和BeanFactory的區別 2. 獲取指定Bean對象 IoC(Inversion …

使用JLink仿真器實現調試打印的N種方法

方法一&#xff1a;使用MCU的串口 這是最古老也是最簡單的方法。 電腦上面插一個USB轉TTL&#xff0c;然后與MCU的UART_RX/UART_TX/GND連接起來。PC端再打開一個串口調試助手。兩邊的波特率一致&#xff0c;就可以收到MCU發過來的打印信息了。 方法二&#xff1a;使用JLink仿…

【EMNLP 2023】面向Stable Diffusion的自動Prompt工程算法

近日&#xff0c;阿里云人工智能平臺PAI與華南理工大學朱金輝教授團隊合作在自然語言處理頂級會議EMNLP2023上發表了BeautifulPrompt的深度生成模型&#xff0c;可以從簡單的圖片描述中生成高質量的提示詞&#xff0c;從而使文生圖模型能夠生成更美觀的圖像。BeautifulPrompt通…

Android--Jetpack--Databinding源碼解析

慢品人間煙火色&#xff0c;閑觀萬事歲月長 一&#xff0c;基本使用 關于databinding的基本使用請看之前的文章 Android--Jetpack--Databinding詳解-CSDN博客 二&#xff0c;xml布局解析 分析源碼呢&#xff0c;主要就是從兩方面入手&#xff0c;一個是使用&#xff0c;一個…

STM32F407-14.1.0-01高級定時器簡介

TIM1 和 TIM8 簡介 高級控制定時器&#xff08;TIM1 和 TIM8&#xff09;包含一個 16 位自動重載計數器&#xff0c;該計數器由可編程預分頻器驅動。 此類定時器可用于各種用途&#xff0c;包括測量輸入信號的脈沖寬度&#xff08;輸入捕獲&#xff09;&#xff0c;或者生成輸出…

微軟NativeApi-NtQuerySystemInformation

微軟有一個比較實用的Native接口&#xff1a;NtQuerySystemInformation&#xff0c;具體可以參考微軟msdn官方文檔&#xff1a;NtQuerySystemInformation&#xff0c; 是一個系統函數&#xff0c;用于收集特定于所提供的指定種類的系統信息。ProcessHacker等工具使用NtQuerySys…

Javascript 數組array賦值與取值

Javascript 數組array賦值與取值 目錄 Javascript 數組array賦值與取值 一、數組元素的賦值 1、在創建Array對象時直接賦值 2、利用Array對象的元素下標對數組進行賦值 二、數組元素的獲取 一、數組元素的賦值 對數組元素賦值共有2種方法&#xff1a; &#xff08;1&am…

每日一題,頭歌平臺c語言題目

任務描述 題目描述:輸入一個字符串&#xff0c;輸出反序后的字符串。 相關知識&#xff08;略&#xff09; 編程要求 請仔細閱讀右側代碼&#xff0c;結合相關知識&#xff0c;在Begin-End區域內進行代碼補充。 輸入 一行字符 輸出 逆序后的字符串 測試說明 樣例輸入&…

項目實戰第四十七講:易寶支付對接詳解(保姆級教程)

易寶支付對接(保姆級教程) 為了實現項目的支付需求,公司選擇了易寶支付進行對接,本文是項目實戰第四十七講,詳解易寶支付對接。 文章目錄 易寶支付對接(保姆級教程)1、需求背景2、流程圖3、技術方案4、相關接口4.1、入駐相關(商戶入網)4.2、賬戶相關接口(充值、提現、…

【LVGL】STM32F429IGT6(在野火官網的LCD例程上)移植LVGL官方的例程(還沒寫完,有問題 排查中)

這里寫目錄標題 前言一、本次實驗準備1、硬件2、軟件 二、移植LVGL代碼1、獲取LVGL官方源碼2、整理一下&#xff0c;下載后的源碼文件3、開始移植 三、移植顯示驅動1、enable LVGL2、修改報錯部分3、修改lv_config4、修改lv_port_disp.c文件到此步遇到的問題 Undefined symbol …