LeetCode LCR 055.二叉搜索樹迭代器

實現一個二叉搜索樹迭代器類BSTIterator ,表示一個按中序遍歷二叉搜索樹(BST)的迭代器:

BSTIterator(TreeNode root) 初始化 BSTIterator 類的一個對象。BST 的根節點 root 會作為構造函數的一部分給出。指針應初始化為一個不存在于 BST 中的數字,且該數字小于 BST 中的任何元素。
boolean hasNext() 如果向指針右側遍歷存在數字,則返回 true ;否則返回 false 。
int next()將指針向右移動,然后返回指針處的數字。
注意,指針初始化為一個不存在于 BST 中的數字,所以對 next() 的首次調用將返回 BST 中的最小元素。

可以假設 next() 調用總是有效的,也就是說,當調用 next() 時,BST 的中序遍歷中至少存在一個下一個數字。

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

輸入
inputs = [“BSTIterator”, “next”, “next”, “hasNext”, “next”, “hasNext”, “next”, “hasNext”, “next”, “hasNext”]
inputs = [[[7, 3, 15, null, null, 9, 20]], [], [], [], [], [], [], [], [], []]
輸出
[null, 3, 7, true, 9, true, 15, true, 20, false]

解釋
BSTIterator bSTIterator = new BSTIterator([7, 3, 15, null, null, 9, 20]);
bSTIterator.next(); // 返回 3
bSTIterator.next(); // 返回 7
bSTIterator.hasNext(); // 返回 True
bSTIterator.next(); // 返回 9
bSTIterator.hasNext(); // 返回 True
bSTIterator.next(); // 返回 15
bSTIterator.hasNext(); // 返回 True
bSTIterator.next(); // 返回 20
bSTIterator.hasNext(); // 返回 False

提示:

樹中節點的數目在范圍 [1, 105] 內
0 <= Node.val <= 106
最多調用 105 次 hasNext 和 next 操作

法一:在構造函數中遞歸計算出中序遍歷的結果:

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class BSTIterator {
public:BSTIterator(TreeNode* root) {inOrder(root);}int next() {return res[iterator++];}bool hasNext() {return iterator < res.size();}private:vector<int> res;int iterator = 0;void inOrder(TreeNode *node){if (node == nullptr){return;}inOrder(node->left);res.push_back(node->val);inOrder(node->right);}
};/*** Your BSTIterator object will be instantiated and called as such:* BSTIterator* obj = new BSTIterator(root);* int param_1 = obj->next();* bool param_2 = obj->hasNext();*/

如果樹中有n個節點,則此算法時間復雜度為O(n),隨后每次調用的時間復雜度為O(1);空間復雜度為O(n),因為要保存中序遍歷的結果。

法二:迭代法,我們可以用棧模擬遞歸,每次調用next時再計算下一個遍歷的結果:

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class BSTIterator {
public:BSTIterator(TreeNode* root) { cur = root;}int next() {while (cur){s.push(cur);cur = cur->left;}cur = s.top();int res = cur->val;s.pop();cur = cur->right;return res;}bool hasNext() {return !s.empty() || (cur != nullptr);}private:stack<TreeNode *> s;TreeNode *cur;
};/*** Your BSTIterator object will be instantiated and called as such:* BSTIterator* obj = new BSTIterator(root);* int param_1 = obj->next();* bool param_2 = obj->hasNext();*/

如果樹中有n個節點,每次調用next的時間復雜度最差為O(n)(當樹退化為鏈表時),均攤時間復雜度為O(1);空間復雜度取決于樹的高度,平均為O(logn),最差為O(n)。

法三:morris遍歷,核心要點是找到前驅節點,如中序遍歷,需要找到當前遍歷節點的前驅節點,即左節點的最右節點nodeLR,將nodeLR的右節點指向當前遍歷到的節點本身:

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class BSTIterator {
public:BSTIterator(TreeNode* root) {cur = root;}int next() {while (cur){if (!cur->left){break;}TreeNode *mostRightOfLeft = getMostRightOfLeft(cur);if (!mostRightOfLeft->right){mostRightOfLeft->right = cur;cur = cur->left;}else if (mostRightOfLeft->right == cur){mostRightOfLeft->right = nullptr;break;}}int res = cur->val;cur = cur->right;return res;}bool hasNext() {return cur;}private:TreeNode *cur;TreeNode *getMostRightOfLeft(TreeNode *node){TreeNode *tmpNode = node->left;// 當右節點為空,或右節點是輸入節點時退出循環while (tmpNode->right && tmpNode->right != node){tmpNode = tmpNode->right;}return tmpNode;}
};/*** Your BSTIterator object will be instantiated and called as such:* BSTIterator* obj = new BSTIterator(root);* int param_1 = obj->next();* bool param_2 = obj->hasNext();*/

此算法時間復雜度為O(1),空間復雜度為O(1)。

法四:二叉搜索,中序遍歷的結果是樹中所有結點從小到大排列,因此每次都找比當前遍歷到的值大的一個節點即可:

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class BSTIterator {
public:BSTIterator(TreeNode* root) : root(root),cur(nullptr) { }int next() {// 首次運行,找最小值if (!cur){cur = root;while (cur->left){cur = cur->left;}return cur->val;}TreeNode *target = getTarget();cur = target;return target->val;}bool hasNext() {// 首次運行時,是否有下一個取決于是否是空樹if (!cur){return root;}// 如果有比當前值大的,就有下一個節點TreeNode *target = getTarget();return target;}private:TreeNode *root;TreeNode *cur;TreeNode *getTarget(){TreeNode *node = root;TreeNode *res = nullptr;while (node){// 找到比當前值大的一個最小節點if (node->val > cur->val){res = node;node = node->left;}else{node = node->right;}}return res;}
};/*** Your BSTIterator object will be instantiated and called as such:* BSTIterator* obj = new BSTIterator(root);* int param_1 = obj->next();* bool param_2 = obj->hasNext();*/

如果樹有n個節點,此算法next和hasNext函數的時間復雜度為O(logn),空間復雜度為O(1)。

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

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

相關文章

vue實現拖拽(vuedraggable)

實現效果: 左側往右側拖動&#xff0c;右側列表可以進行拖拽排序。 安裝引用&#xff1a; npm install vuedraggable import draggable from vuedraggable 使用&#xff1a; data數據&#xff1a; componentList: [{groupName: 考試題型,children: [{componentType: danxua…

SQLite 的使用

SQLite 是一個輕量級、自包含和無服務器的關系型數據庫管理系統&#xff08;RDBMS&#xff09;&#xff0c;廣泛應用于嵌入式系統、移動應用程序和小中型網站。它易于創建、需要的配置較少&#xff0c;并且提供了用于管理和操作數據的強大功能集。本文&#xff0c;我們將帶領你…

電路設計(26)——交通信號燈的multism仿真

1.功能要求 使用數字芯片設計一款交通信號燈&#xff0c;使得&#xff1a; 主干道的綠燈時間為60S&#xff0c;紅燈時間為45S 次干道的紅燈時間為60S&#xff0c;綠燈時間為45S 主、次干道&#xff0c;綠燈的最后5S內&#xff0c;黃燈閃爍 使用數碼管顯示各自的倒計時時間。 按…

【CMake】(5)搜索文件

方法1:使用aux_source_directory命令 aux_source_directory命令用于查找指定目錄下的所有源文件,并將文件列表存儲到一個變量中。這種方法簡單易用,適合于源文件位于單一目錄下的情況。 基本語法如下: aux_source_directory(<dir> <variable>)<dir>:…

openssl3.2 - 編譯 - zlib.dll不要使用絕對路徑

文章目錄 openssl3.2 - 編譯 - 編譯時的動態庫zlib.dll不要使用絕對路徑概述測試zlib特性在安裝好的目錄中是否正常筆記70-test_tls13certcomp.t80-test_cms.t對測試環境的猜測從頭再編譯測試安裝一次測試一下隨便改變位置的openssl用到zlib時是否好使測試一下隨便改變位置的op…

Docker Nginx 負載均衡搭建(服務宕機-配置高可用) - 附(Python案例,其它語言同理)

目錄 一 . 概要 1. 什么是負載均衡 2. 負載均衡有哪些優勢&#xff1f; &#xff08;1&#xff09;應用程序可用性 &#xff08;2&#xff09;應用程序可擴展性 &#xff08;3&#xff09;應用程序安全 &#xff08;4&#xff09;應用程序性能 3 . Nginx負載均衡調度策…

Java高級 / 架構師 場景方案 面試題(二)

1.雙十一億級用戶日活統計如何用 Redis快速計算 在雙十一這種億級用戶日活統計的場景中&#xff0c;使用Redis進行快速計算的關鍵在于利用Redis的數據結構和原子操作來高效地統計和計算數據。以下是一個基于Redis的日活統計方案&#xff1a; 選擇合適的數據結構&#xff1a; …

核密度分析

一.算法介紹 核密度估計&#xff08;Kernel Density Estimation&#xff09;是一種用于估計數據分布的非參數統計方法。它可以用于多種目的和應用&#xff0c;包括&#xff1a; 數據可視化&#xff1a;核密度估計可以用來繪制平滑的密度曲線或熱力圖&#xff0c;從而直觀地表…

【DOCKER】隨手記

目錄 1. 安裝1.1 LINUX1.2 Windows 2. 常用配置2.1 普通權限運行2.2 開機自啟動2.3 3 更換Docker鏡像源2.4 更改默認存儲位置 3. 顯示帶UI的軟件4. 基于DOCKER的服務4.1 FTP4.2 Portainer4.3 Watchtower4.4 SiYuan4.5 GitLab4.5.1 創建容器4.5.2 克隆路徑問題4.5.3 獲取默認密碼…

win系統下安裝php8.3版本并配置環境變量的詳細教程

本篇文章主要講解在win系統下安裝和配置php8.3版本&#xff0c;并配置環境變量的詳細教程。 日期&#xff1a;2024年2月22日 作者&#xff1a;任聰聰 一、下載php8.3版本包 php8.3版本官方下載地址&#xff1a;https://windows.php.net/download#php-8.3 步驟一、打開下載地址…

【Unity】Unity與安卓交互

問題描述 Unity和安卓手機進行交互&#xff0c;是我們開發游戲中最常見的場景。本教程將從一個簡單的例子來演示一下。 本教程需要用到Android Studio2021.1.1 1.Android Studio新建一個工程 2.選擇Empty Activity 然后點擊Next 3.點擊Finish完成創建 4.選擇File-New-New Mo…

【python 3.9.18】windowns安裝版

因為這個版本官方未提供&#xff0c;所以需要自己編譯出來&#xff0c;其他沒有的版本可以依據下面的進行生成一個exe也可行。 成品&#xff1a; https://gitee.com/greatLong/python-3.9.18/tree/master/python-3.9.18/PCbuild/amd64 1、環境準備 需要使用到 這里面還需要選…

【MATLAB GUI】 5. 圖像處理菜單(菜單編輯器)

看B站up主freexyn的freexyn編程實例視頻教程系列36Matlab GUI的學習筆記 任務要求設計一個圖像處理菜單&#xff0c;實現圖像的打開導入、灰度處理、存儲等功能 修改過文件名&#xff0c;所以運行的時候會有一點點報錯&#xff0c;但是不影響運行 打開工具欄下邊的菜單編輯器…

開窗Window和WindowAll的區別

在 Apache Flink 流處理框架中&#xff0c;窗口操作是處理流數據的重要部分。Flink 提供了時間窗口、計數窗口等多種窗口類型&#xff0c;用于將數據分割成不同的窗口進行聚合或其他處理。 Window 和 WindowAll 是 Flink 中窗口操作的兩種不同方式&#xff0c;它們分別對應不同…

GIT倉庫轉移--攜帶原分支及提交記錄

背景&#xff1a;最近公司倉庫位置需要移動&#xff0c;想保留原有的倉庫分支和提交記錄 操作&#xff1a; 目的位置新建倉庫&#xff08;要保證創建無誤&#xff09;原倉庫 git clone 到本地&#xff0c;git pull 保證代碼最新找到原倉庫.git/config 文件&#xff0c;修改 rem…

EPSON機器人與PC上位機軟件C#網絡TCP通訊

項目背景&#xff1a; 在非標設備PIN焊接機中用到了愛普生機器人。上位機軟件使用c#wpf開發。主要邏輯在上位機中。用愛普生機器人給焊接平臺實現自動上下料。 通訊方式&#xff1a;網絡TCP通訊&#xff0c;Socket 角色&#xff1a;上位機為服務端&#xff0c;機器人為客戶端…

Linux|centos7|錄屏神器asciinema的編譯安裝和離線化安裝使用

前言&#xff1a; asciinema這個錄屏軟件前面有一點研究&#xff0c;但它的部署安裝比較麻煩&#xff0c;雖然此軟件的安裝部署方式是很多的&#xff0c;比如yum安&#xff0c;apt&#xff0c;brew&#xff0c;docker&#xff0c;pip&#xff0c;rust編譯&#xff0c;docker等…

創建一個基于Node.js的實時聊天應用

在當今數字化社會&#xff0c;實時通訊已成為人們生活中不可或缺的一部分。無論是在社交媒體平臺上與朋友交流&#xff0c;還是在工作場合中與同事協作&#xff0c;實時聊天應用都扮演著重要角色。與此同時&#xff0c;Node.js作為一種流行的后端技術&#xff0c;為開發者提供了…

CrossOver虛擬機軟件2024有哪些功能?最新版本支持哪些游戲?

CrossOver由codewaver公司開發的類虛擬機軟件&#xff0c;目的是使linux和Mac OS X操作系統和window系統兼容。CrossOver不像Parallels或VMware的模擬器&#xff0c;而是實實在在Mac OS X系統上運行的一個軟件。CrossOvers能夠直接在Mac上運行Windows軟件與游戲&#xff0c;而不…

Java架構師之路七、大數據:Hadoop、Spark、Hive、HBase、Kafka等

目錄 Hadoop&#xff1a; Spark&#xff1a; Hive&#xff1a; HBase&#xff1a; Kafka&#xff1a; Java架構師之路六、高并發與性能優化&#xff1a;高并發編程、性能調優、線程池、NIO、Netty、高性能數據庫等。-CSDN博客Java架構師之路八、安全技術&#xff1a;Web安…