給定乙個二叉搜尋樹,編寫乙個函式 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,然後,很容易會寫出下面的錯誤**
仔細想想可以發現,上面的錯誤在於,當在中序遍歷到中,k自減後,整個遞迴函式從底向上返回到上一層時,自減後的值並沒有傳遞到上一層,//錯誤**
int result=0;
void
inorderrecursion
(treenode* root,
int k)
inorderrecursion
(root-
>right,k);}
intkthsmallest
(treenode* root,
int k)
舉例:輸入
[7,5,8,1,6,null,10]
k=3時,這個函式的遞迴過程如下圖,可知最後result會等於10,並不是我們想象中的6。
為了解決上面的問題,我們要想辦法把底層遞迴函式自減k後的結果傳遞到上一層,
一種做法是,傳參時傳入k的引用。
這個函式的遞迴過程如下圖,可知最後result會等於6。int result=0;
//注意這裡傳入的是int& k
void
inorderrecursion
(treenode* root,
int& k)
inorderrecursion
(root-
>right,k)
;return;}
intkthsmallest
(treenode* root,
int k)
另一種做法是,我們在定義乙個額外的外部變數num,每次在都對這個外部變數自增,當num自增到k時,賦值給外部變數result。當然,歸根結底,都是把底層遞迴函式計數變化後的結果傳遞到上一層
有了上面的遞迴解法,然後可以利用棧,將上面的解法改為非遞迴的形式
劍指 offer 54. 二叉搜尋樹的第k大節點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)
給定一棵二叉搜尋樹,請找出其中第k大的節點。
跟上面的題一樣,用上面的**改改,就可以解決這個問題。struct treenode
注意是返回第k大的節點,而不是第k小的節點,所以得改變一下中序遍歷,改為「右子樹-根-左子樹「
要想把底層遞迴函式計數變化後的結果傳遞到上一層,要麼傳遞得是k的引用,要麼定義乙個全域性變數用於計數。class
solution
//後左子樹
kthlargest
(root-
>left,k);}
//中序遍歷
intkthlargest
(treenode* root,
int 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...