二叉搜尋樹的第k個結點

2021-10-07 20:29:53 字數 4078 閱讀 5340

給定乙個二叉搜尋樹,編寫乙個函式 kthsmallest 來查詢其中第 k 個最小的元素。

說明:你可以假設 k 總是有效的,1 ≤ k ≤ 二叉搜尋樹元素個數。

提供的函式介面如下:

/**

* definition for a binary tree node.

* struct treenode

* treenode(int x) : val(x), left(nullptr), right(nullptr) {}

* treenode(int x, treenode *left, treenode *right) : val(x), left(left), right(right) {}

* };

*/class

solution

};

思路:主要是根據二叉樹的中序遍歷來求第k個節點。

先複習下最原始的二叉樹中序遍歷框架

//中序遍歷,遞迴

//遞迴

void

midorderrecursion

(treenode* root)

利用棧模擬遞迴過程,思路如下:

對於給定的二叉樹根結點 root,

(1)若其左孩子不為空,迴圈將 root及 root左子樹中的所有結點的左孩子入棧;

(2)取棧頂元素 cur,訪問 cur 並將 cur 出棧。然後對 cur 的右子結點進行步驟(1)那樣的處理;

(3)重複(1)和(2)的操作,直到 cur 為空且棧為空。

void

midorderstack

(treenode* root)

cur=stack.

top();

cout<

>value<

cur=cur-

>right;

stack.

pop();

}}

再看看這一題怎麼改造原始的遞迴框架

先考慮用遞迴的方式求解

void

midorderrecursion

(treenode* root)

先看看題目原始的函式宣告如下,若直接在題目給定的這個函式介面下做中序遞迴,你會發現

if(root==nullptr) 時,你不知道返回什麼,所以我們另外定義乙個輔助函式來做中序遞迴。

int

kthsmallest

(treenode* root,

int k)

所以新增乙個輔助函式,

void

inorderrecursion

(treenode* root,

int k)

定義了這個輔助函式後,處理base case的返回值容易了,但是你發現,怎麼把第k個節點的值傳遞出去呢?

這裡有一種很簡單的做法

就是用乙個序列容器,比如vector,儲存中序遍歷的所有結果,最後返回這個容器中的第k個元素,

我們只用將原始中序遍歷框架中 cout<< root->value這裡可以定義乙個外部變數result,在遍歷到第k個節點時,將值賦給result,然後,很容易會寫出下面的錯誤**

//錯誤**

int result=0;

void

inorderrecursion

(treenode* root,

int k)

inorderrecursion

(root-

>right,k);}

intkthsmallest

(treenode* root,

int k)

仔細想想可以發現,上面的錯誤在於,當在中序遍歷到中,k自減後,整個遞迴函式從底向上返回到上一層時,自減後的值並沒有傳遞到上一層

舉例:輸入

[7,5,8,1,6,null,10]

k=3時,這個函式的遞迴過程如下圖,可知最後result會等於10,並不是我們想象中的6。

為了解決上面的問題,我們要想辦法把底層遞迴函式自減k後的結果傳遞到上一層

一種做法是,傳參時傳入k的引用。

int result=0;

//注意這裡傳入的是int& k

void

inorderrecursion

(treenode* root,

int& k)

inorderrecursion

(root-

>right,k)

;return;}

intkthsmallest

(treenode* root,

int k)

這個函式的遞迴過程如下圖,可知最後result會等於6。

另一種做法是,我們在定義乙個額外的外部變數num,每次在都對這個外部變數自增,當num自增到k時,賦值給外部變數result。當然,歸根結底,都是把底層遞迴函式計數變化後的結果傳遞到上一層

有了上面的遞迴解法,然後可以利用棧,將上面的解法改為非遞迴的形式

int result=0;

void

inorderstack

(treenode* root,

int& k)

//左子樹最低節點出棧

cur=mystack.

top();

if(--k==0)

mystack.

pop();

//對左子樹最低節點的右子樹做同樣的事情

cur=cur-

>right;}}

intkthsmallest

(treenode* root,

int k)

劍指 offer 54. 二叉搜尋樹的第k大節點

給定一棵二叉搜尋樹,請找出其中第k大的節點。

struct treenode
跟上面的題一樣,用上面的**改改,就可以解決這個問題。

注意是返回第k大的節點,而不是第k小的節點,所以得改變一下中序遍歷,改為「右子樹-根-左子樹「

class

solution

//後左子樹

kthlargest

(root-

>left,k);}

//中序遍歷

intkthlargest

(treenode* root,

int k)

};

要想把底層遞迴函式計數變化後的結果傳遞到上一層,要麼傳遞得是k的引用,要麼定義乙個全域性變數用於計數。

二叉搜尋樹第k個結點

題目描述 給定一顆二叉搜尋樹,請找出其中的第k大的結點。例如,5 3 7 2 4 6 8 中,按結點數值大小順序第三個結點的值為4。這個題目考慮到可以用中序遍歷求解,因為中序遍歷是搜尋二叉樹的從大到小的順序,對二叉樹進行中序遍歷,每次經過結點k值減一,一直到k值等於1,對應的結點就是要尋找的點,這個...

二叉搜尋樹的第k個結點

二叉搜尋樹的第k個結點 題目描述 給定一顆二叉搜尋樹,請找出其中的第k大的結點。例如,5 3 7 2 4 6 8 中,按結點數值大小順序第三個結點的值為4。思路 二叉搜尋樹為關鍵字排序 左子樹 根 右子樹 二叉樹的中序遍歷的訪問順序為 左子樹 根 右子樹 故找出二叉搜尋樹中第k大的節點實質為找出中序...

二叉搜尋樹的第k個結點

給定一棵二叉搜尋樹,請找出其中的第k小的結點。例如,5,3,7,2,4,6,8 中,按結點數值大小順序第三小結點的值為4。時間限制 1秒 空間限制 32768k 熱度指數 146968 中序遍歷二叉搜尋樹得到的則為乙個有序的陣列。因此,通過中序遍歷二叉搜尋樹則可得到結果 struct treenod...