日B视频 亚洲,啪啪啪网站一区二区,91色情精品久久,日日噜狠狠色综合久,超碰人妻少妇97在线,999青青视频,亚洲一区二卡,让本一区二区视频,日韩网站推荐

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

二叉樹上應該怎么求

算法與數(shù)據(jù)結構 ? 來源:代碼隨想錄 ? 作者:程序員Carl ? 2021-11-22 11:32 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

二叉樹上應該怎么求,二叉搜索樹上又應該怎么求?

在求眾數(shù)集合的時候有一個技巧,因為題目中眾數(shù)是可以有多個的,所以一般的方法需要遍歷兩遍才能求出眾數(shù)的集合。

但可以遍歷一遍就可以求眾數(shù)集合,使用了適時清空結果集的方法,這個方法還是很巧妙的。相信仔細讀了文章的同學會驚呼其巧妙!

501.二叉搜索樹中的眾數(shù)

題目鏈接:https://leetcode-cn.com/problems/find-mode-in-binary-search-tree/solution

給定一個有相同值的二叉搜索樹(BST),找出 BST 中的所有眾數(shù)(出現(xiàn)頻率最高的元素)。

假定 BST 有如下定義:

  • 結點左子樹中所含結點的值小于等于當前結點的值
  • 結點右子樹中所含結點的值大于等于當前結點的值
  • 左子樹和右子樹都是二叉搜索樹

例如:

給定 BST [1,null,2,2],

返回[2].

提示:如果眾數(shù)超過1個,不需考慮輸出順序

進階:你可以不使用額外的空間嗎?(假設由遞歸產(chǎn)生的隱式調用棧的開銷不被計算在內)

思路

這道題目呢,遞歸法我從兩個維度來講。

首先如果不是二叉搜索樹的話,應該怎么解題,是二叉搜索樹,又應該如何解題,兩種方式做一個比較,可以加深大家對二叉樹的理解。

遞歸法

如果不是二叉搜索樹

如果不是二叉搜索樹,最直觀的方法一定是把這個樹都遍歷了,用map統(tǒng)計頻率,把頻率排個序,最后取前面高頻的元素的集合。

具體步驟如下:

  1. 這個樹都遍歷了,用map統(tǒng)計頻率

至于用前中后序那種遍歷也不重要,因為就是要全遍歷一遍,怎么個遍歷法都行,層序遍歷都沒毛??!

這里采用前序遍歷,代碼如下:

//mapkey:元素,value:出現(xiàn)頻率
voidsearchBST(TreeNode*cur,unordered_map<int,int>&map){//前序遍歷
if(cur==NULL)return;
map[cur->val]++;//統(tǒng)計元素頻率
searchBST(cur->left,map);
searchBST(cur->right,map);
return;
}
  1. 把統(tǒng)計的出來的出現(xiàn)頻率(即map中的value)排個序

有的同學可能可以想直接對map中的value排序,還真做不到,C++中如果使用std::map或者std::multimap可以對key排序,但不能對value排序。

所以要把map轉化數(shù)組即vector,再進行排序,當然vector里面放的也是pair類型的數(shù)據(jù),第一個int為元素,第二個int為出現(xiàn)頻率。

代碼如下:

boolstaticcmp(constpair&a,constpair&b){
returna.second>b.second;//按照頻率從大到小排序
}

vector>vec(map.begin(),map.end());
sort(vec.begin(),vec.end(),cmp);//給頻率排個序
  1. 取前面高頻的元素

此時數(shù)組vector中已經(jīng)是存放著按照頻率排好序的pair,那么把前面高頻的元素取出來就可以了。

代碼如下:

result.push_back(vec[0].first);
for(inti=1;i//取最高的放到result數(shù)組中
if(vec[i].second==vec[0].second)result.push_back(vec[i].first);
elsebreak;
}
returnresult;

整體C++代碼如下:

classSolution{
private:

voidsearchBST(TreeNode*cur,unordered_map<int,int>&map){//前序遍歷
if(cur==NULL)return;
map[cur->val]++;//統(tǒng)計元素頻率
searchBST(cur->left,map);
searchBST(cur->right,map);
return;
}
boolstaticcmp(constpair<int,int>&a,constpair<int,int>&b){
returna.second>b.second;
}
public:
vector<int>findMode(TreeNode*root){
unordered_map<int,int>map;//key:元素,value:出現(xiàn)頻率
vector<int>result;
if(root==NULL)returnresult;
searchBST(root,map);
vectorint,int>>vec(map.begin(),map.end());
sort(vec.begin(),vec.end(),cmp);//給頻率排個序
result.push_back(vec[0].first);
for(inti=1;i//取最高的放到result數(shù)組中
if(vec[i].second==vec[0].second)result.push_back(vec[i].first);
elsebreak;
}
returnresult;
}
};

所以如果本題沒有說是二叉搜索樹的話,那么就按照上面的思路寫!

是二叉搜索樹

既然是搜索樹,它中序遍歷就是有序的

中序遍歷代碼如下:

voidsearchBST(TreeNode*cur){
if(cur==NULL)return;
searchBST(cur->left);//左
(處理節(jié)點)//中
searchBST(cur->right);//右
return;
}

遍歷有序數(shù)組的元素出現(xiàn)頻率,從頭遍歷,那么一定是相鄰兩個元素作比較,然后就把出現(xiàn)頻率最高的元素輸出就可以了。

關鍵是在有序數(shù)組上的話,好搞,在樹上怎么搞呢?

這就考察對樹的操作了。

二叉樹:搜索樹的最小絕對差中我們就使用了pre指針和cur指針的技巧,這次又用上了。

弄一個指針指向前一個節(jié)點,這樣每次cur(當前節(jié)點)才能和pre(前一個節(jié)點)作比較。

而且初始化的時候pre = NULL,這樣當pre為NULL時候,我們就知道這是比較的第一個元素。

代碼如下:

if(pre==NULL){//第一個節(jié)點
count=1;//頻率為1
}elseif(pre->val==cur->val){//與前一個節(jié)點數(shù)值相同
count++;
}else{//與前一個節(jié)點數(shù)值不同
count=1;
}
pre=cur;//更新上一個節(jié)點

此時又有問題了,因為要求最大頻率的元素集合(注意是集合,不是一個元素,可以有多個眾數(shù)),如果是數(shù)組上大家一般怎么辦?

應該是先遍歷一遍數(shù)組,找出最大頻率(maxCount),然后再重新遍歷一遍數(shù)組把出現(xiàn)頻率為maxCount的元素放進集合。(因為眾數(shù)有多個)

這種方式遍歷了兩遍數(shù)組。

那么我們遍歷兩遍二叉搜索樹,把眾數(shù)集合算出來也是可以的。

但這里其實只需要遍歷一次就可以找到所有的眾數(shù)。

那么如何只遍歷一遍呢?

如果 頻率count 等于 maxCount(最大頻率),當然要把這個元素加入到結果集中(以下代碼為result數(shù)組),代碼如下:

if(count==maxCount){//如果和最大值相同,放進result中
result.push_back(cur->val);
}

是不是感覺這里有問題,result怎么能輕易就把元素放進去了呢,萬一,這個maxCount此時還不是真正最大頻率呢。

所以下面要做如下操作:

頻率count 大于 maxCount的時候,不僅要更新maxCount,而且要清空結果集(以下代碼為result數(shù)組),因為結果集之前的元素都失效了。

if(count>maxCount){//如果計數(shù)大于最大值
maxCount=count;//更新最大頻率
result.clear();//很關鍵的一步,不要忘記清空result,之前result里的元素都失效了
result.push_back(cur->val);
}

關鍵代碼都講完了,完整代碼如下:(只需要遍歷一遍二叉搜索樹,就求出了眾數(shù)的集合

classSolution{
private:
intmaxCount;//最大頻率
intcount;//統(tǒng)計頻率
TreeNode*pre;
vector<int>result;
voidsearchBST(TreeNode*cur){
if(cur==NULL)return;

searchBST(cur->left);//左
//中
if(pre==NULL){//第一個節(jié)點
count=1;
}elseif(pre->val==cur->val){//與前一個節(jié)點數(shù)值相同
count++;
}else{//與前一個節(jié)點數(shù)值不同
count=1;
}
pre=cur;//更新上一個節(jié)點

if(count==maxCount){//如果和最大值相同,放進result中
result.push_back(cur->val);
}

if(count>maxCount){//如果計數(shù)大于最大值頻率
maxCount=count;//更新最大頻率
result.clear();//很關鍵的一步,不要忘記清空result,之前result里的元素都失效了
result.push_back(cur->val);
}

searchBST(cur->right);//右
return;
}

public:
vector<int>findMode(TreeNode*root){
count=0;
maxCount=0;
TreeNode*pre=NULL;//記錄前一個節(jié)點
result.clear();

searchBST(root);
returnresult;
}
};

迭代法

只要把中序遍歷轉成迭代,中間節(jié)點的處理邏輯完全一樣。

二叉樹前中后序轉迭代,傳送門:

下面我給出其中的一種中序遍歷的迭代法,其中間處理邏輯一點都沒有變(我從遞歸法直接粘過來的代碼,連注釋都沒改,哈哈)

代碼如下:

classSolution{
public:
vector<int>findMode(TreeNode*root){
stackst;
TreeNode*cur=root;
TreeNode*pre=NULL;
intmaxCount=0;//最大頻率
intcount=0;//統(tǒng)計頻率
vector<int>result;
while(cur!=NULL||!st.empty()){
if(cur!=NULL){//指針來訪問節(jié)點,訪問到最底層
st.push(cur);//將訪問的節(jié)點放進棧
cur=cur->left;//左
}else{
cur=st.top();
st.pop();//中
if(pre==NULL){//第一個節(jié)點
count=1;
}elseif(pre->val==cur->val){//與前一個節(jié)點數(shù)值相同
count++;
}else{//與前一個節(jié)點數(shù)值不同
count=1;
}
if(count==maxCount){//如果和最大值相同,放進result中
result.push_back(cur->val);
}

if(count>maxCount){//如果計數(shù)大于最大值頻率
maxCount=count;//更新最大頻率
result.clear();//很關鍵的一步,不要忘記清空result,之前result里的元素都失效了
result.push_back(cur->val);
}
pre=cur;
cur=cur->right;//右
}
}
returnresult;
}
};

總結

本題在遞歸法中,我給出了如果是普通二叉樹,應該怎么求眾數(shù)。

知道了普通二叉樹的做法時候,我再進一步給出二叉搜索樹又應該怎么求眾數(shù),這樣鮮明的對比,相信會對二叉樹又有更深層次的理解了。

在遞歸遍歷二叉搜索樹的過程中,我還介紹了一個統(tǒng)計最高出現(xiàn)頻率元素集合的技巧, 要不然就要遍歷兩次二叉搜索樹才能把這個最高出現(xiàn)頻率元素的集合求出來。

為什么沒有這個技巧一定要遍歷兩次呢?因為要求的是集合,會有多個眾數(shù),如果規(guī)定只有一個眾數(shù),那么就遍歷一次穩(wěn)穩(wěn)的了。

最后我依然給出對應的迭代法,其實就是迭代法中序遍歷的模板加上遞歸法中中間節(jié)點的處理邏輯,分分鐘就可以寫出來,中間邏輯的代碼我都是從遞歸法中直接粘過來的。

求二叉搜索樹中的眾數(shù)其實是一道簡單題,但大家可以發(fā)現(xiàn)我寫了這么一大篇幅的文章來講解,主要是為了盡量從各個角度對本題進剖析,幫助大家更快更深入理解二叉樹。

需要強調的是 leetcode上的耗時統(tǒng)計是非常不準確的,看個大概就行,一樣的代碼耗時可以差百分之50以上,所以leetcode的耗時統(tǒng)計別太當回事,知道理論上的效率優(yōu)劣就行了。

其他語言版本

Java

暴力法

classSolution{
publicint[]findMode(FindModeInBinarySearchTree.TreeNoderoot){
Mapmap=newHashMap<>();
Listlist=newArrayList<>();
if(root==null)returnlist.stream().mapToInt(Integer::intValue).toArray();
//獲得頻率Map
searchBST(root,map);
List>mapList=map.entrySet().stream()
.sorted((c1,c2)->c2.getValue().compareTo(c1.getValue()))
.collect(Collectors.toList());
list.add(mapList.get(0).getKey());
//把頻率最高的加入list
for(inti=1;iif(mapList.get(i).getValue()==mapList.get(i-1).getValue()){
list.add(mapList.get(i).getKey());
}else{
break;
}
}
returnlist.stream().mapToInt(Integer::intValue).toArray();
}

voidsearchBST(FindModeInBinarySearchTree.TreeNodecurr,Mapmap){
if(curr==null)return;
map.put(curr.val,map.getOrDefault(curr.val,0)+1);
searchBST(curr.left,map);
searchBST(curr.right,map);
}

}
classSolution{
ArrayListresList;
intmaxCount;
intcount;
TreeNodepre;

publicint[]findMode(TreeNoderoot){
resList=newArrayList<>();
maxCount=0;
count=0;
pre=null;
findMode1(root);
int[]res=newint[resList.size()];
for(inti=0;ireturnres;
}

publicvoidfindMode1(TreeNoderoot){
if(root==null){
return;
}
findMode1(root.left);

introotValue=root.val;
//計數(shù)
if(pre==null||rootValue!=pre.val){
count=1;
}else{
count++;
}
//更新結果以及maxCount
if(count>maxCount){
resList.clear();
resList.add(rootValue);
maxCount=count;
}elseif(count==maxCount){
resList.add(rootValue);
}
pre=root;

findMode1(root.right);
}
}

Python

遞歸法

classSolution:
deffindMode(self,root:TreeNode)->List[int]:
ifnotroot:return
self.pre=root
self.count=0//統(tǒng)計頻率
self.countMax=0//最大頻率
self.res=[]
deffindNumber(root):
ifnotroot:returnNone//第一個節(jié)點
findNumber(root.left)//左
ifself.pre.val==root.val://中:與前一個節(jié)點數(shù)值相同
self.count+=1
else://與前一個節(jié)點數(shù)值不同
self.pre=root
self.count=1
ifself.count>self.countMax://如果計數(shù)大于最大值頻率
self.countMax=self.count//更新最大頻率
self.res=[root.val]//更新res
elifself.count==self.countMax://如果和最大值相同,放進res中
self.res.append(root.val)
findNumber(root.right)//右
return
findNumber(root)
returnself.res

迭代法-中序遍歷-不使用額外空間,利用二叉搜索樹特性

classSolution:
deffindMode(self,root:TreeNode)->List[int]:
stack=[]
cur=root
pre=None
maxCount,count=0,0
res=[]
whilecurorstack:
ifcur:#指針來訪問節(jié)點,訪問到最底層
stack.append(cur)
cur=cur.left
else:#逐一處理節(jié)點
cur=stack.pop()
ifpre==None:#第一個節(jié)點
count=1
elifpre.val==cur.val:#與前一個節(jié)點數(shù)值相同
count+=1
else:
count=1
ifcount==maxCount:
res.append(cur.val)
ifcount>maxCount:
maxCount=count
res.clear()
res.append(cur.val)

pre=cur
cur=cur.right
returnres


責任編輯:haq
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • SQL
    SQL
    +關注

    關注

    1

    文章

    807

    瀏覽量

    46964
  • 二叉樹
    +關注

    關注

    0

    文章

    74

    瀏覽量

    13010

原文標題:二叉搜索樹中的眾數(shù)是多少?

文章出處:【微信號:TheAlgorithm,微信公眾號:算法與數(shù)據(jù)結構】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    產(chǎn)能過剩還是供不應?深度解析全球芯片代工市場現(xiàn)狀

    芯片卻供不應,先進封裝產(chǎn)能更是爭奪焦點。這一分化源于頭部代工廠戰(zhàn)略投資向先進制程和區(qū)域化成熟產(chǎn)能轉移,行業(yè)正處重置再平衡周期,中長期 AI、汽車電子等將成需求核心,適配特定需求的代工廠更具競爭力。
    的頭像 發(fā)表于 01-29 11:16 ?462次閱讀

    TüV萊茵與杭集團達成戰(zhàn)略合作并頒發(fā)歐盟CE-MD符合性證書

    日前,國際獨立第三方檢測、檢驗和認證機構德國萊茵TüV大中華區(qū)(簡稱"TüV萊茵")與杭集團股份有限公司(簡稱"杭集團")簽署了戰(zhàn)略合作協(xié)議,標志著雙方
    的頭像 發(fā)表于 01-15 12:18 ?472次閱讀

    億緯鋰能與杭集團達成戰(zhàn)略合作

    近日,億緯鋰能與杭集團2025年戰(zhàn)略研討會暨戰(zhàn)略合作協(xié)議簽約儀式在杭州舉行。億緯鋰能副總裁、商用車電池產(chǎn)品線總裁江吉兵博士,億緯鋰能商用車電池產(chǎn)品線國內銷售部總經(jīng)理井振江,杭集團董事、副總經(jīng)理兼
    的頭像 發(fā)表于 01-04 18:18 ?1197次閱讀

    C語言的常見算法

    = next; } return prev; } ``` ### 二叉樹遍歷 (前序) ```c struct TreeNode { int val; struct TreeNode
    發(fā)表于 11-24 08:29

    高頻整流應該選用哪些MDD極管?核心參數(shù)與物理機制詳解

    在高頻整流應用中,選擇什么MDD極管不是簡單的“耐壓夠就行”,而是必須綜合考慮反向恢復、正向壓降、漏電、溫升、浪涌能力,以及最終電路效率與EMI。許多工程師在幾十kHz以下仍然可以采用普通整流管
    的頭像 發(fā)表于 11-18 10:50 ?534次閱讀
    高頻整流<b class='flag-5'>應該</b>選用哪些MDD<b class='flag-5'>二</b>極管?核心參數(shù)與物理機制詳解

    通過優(yōu)化代碼來提高MCU運行效率

    選擇時間復雜度低的算法。 根據(jù)訪問模式選擇數(shù)據(jù)結構。頻繁查找用哈希表,有序數(shù)據(jù)用二叉樹等。 查表法:對于復雜的數(shù)學計算(如sin, log),或者協(xié)議解析,預先計算好結果存于數(shù)組中,用空間換時間
    發(fā)表于 11-12 08:21

    蜂鳥E203內核中斷管理模塊sirv_plic_man代碼分析

    。 上面的代碼生成一個二叉樹結構來比較和選擇具有最大優(yōu)先級的掛起中斷源及其ID。樹狀結構由級聯(lián)比較器組成,每一層的比較器數(shù)量是前一層的一半。在樹的每一層,選擇優(yōu)先級最高的中斷并傳遞到下一層,直到只剩下
    發(fā)表于 10-23 06:05

    請問rtt studio 的文件夾打紅什么意思?

    rtt studio 的文件夾打紅什么意思?而且文件夾里面實際是有文件的,但是瀏覽不出來。
    發(fā)表于 09-18 06:34

    使用TC387芯片進行設計,請問引腳配置工具應該下載哪個板機支持包(bsp)呢?

    使用TC387芯片進行設計,請問引腳配置工具應該下載哪個板機支持包(bsp)呢?這個問題最近一直沒有解決,大佬指點!
    發(fā)表于 08-11 07:53

    在高溫或高振動環(huán)境下,整流極管的降額曲線應該如何調整?

    在高溫或高振動環(huán)境下,整流極管的降額曲線需結合熱力學和機械應力進行綜合調整,以確保長期可靠性。以下是具體調整策略及設計要點:一、高溫環(huán)境下的降額曲線調整1.溫度對電流能力的限制整流極管的額定電流
    的頭像 發(fā)表于 07-16 10:51 ?1251次閱讀
    在高溫或高振動環(huán)境下,整流<b class='flag-5'>二</b>極管的降額曲線<b class='flag-5'>應該</b>如何調整?

    億緯鋰能榮獲杭集團2022-2024年度優(yōu)秀供應商獎

    近日,億緯鋰能憑借卓越產(chǎn)品、可靠交付與優(yōu)質服務榮獲杭集團頒發(fā)的“2022-2024年度優(yōu)秀供應商”獎。杭集團副總經(jīng)理兼杭電器董事長金華曙、杭電器總經(jīng)理兼杭博電機總經(jīng)理李明輝出席
    的頭像 發(fā)表于 07-15 09:00 ?1132次閱讀

    電解電容的ESR值應該如何控制?

    電解電容的ESR值應該如何控制?在電子電路設計中,電解電容的等效串聯(lián)電阻(ESR)值對電路性能有著顯著影響。ESR值過高會導致電容發(fā)熱、效率降低,甚至影響電路穩(wěn)定性。因此,控制電解電容的ESR值
    的頭像 發(fā)表于 06-20 15:20 ?1722次閱讀
    電解電容的ESR值<b class='flag-5'>應該</b>如何控制?

    下一代高速芯片晶體管解制造問題解決了!

    步驟造成的損壞,并且可以使用成熟的氧化硅材料和工具來構建。 由于現(xiàn)在的壁厚為 15 納米,這可能會影響晶體管密度,因為外壁片器件比內壁片晶體管更大。然而,外壁片晶體管提供的可制
    發(fā)表于 06-20 10:40

    蘇州高美達選購我司HS-TGA-101熱重分析儀

    在材料研究與生產(chǎn)領域,精準分析材料熱性能至關重要。蘇州高美達公司經(jīng)過多方調研與嚴格測試,最終選定我司的HS-TGA-101熱重分析儀,為其材料研發(fā)與質量把控注入強大助力。蘇州高美達熱重分析(TG
    的頭像 發(fā)表于 06-12 09:47 ?999次閱讀
    蘇州高<b class='flag-5'>求</b>美達選購我司HS-TGA-101熱重分析儀

    taVNS經(jīng)耳迷走神經(jīng)電刺激適應癥之緩解偏頭痛

    神經(jīng)血管系統(tǒng)與中樞敏化偏頭痛的核心病理機制涉及三神經(jīng)血管系統(tǒng)的異常激活。三神經(jīng)節(jié)(TrigeminalGanglion)的C纖維釋放降鈣素基因相關肽(CGRP)和P物質,引發(fā)神經(jīng)源性炎癥和硬
    的頭像 發(fā)表于 05-21 20:58 ?2855次閱讀
    taVNS經(jīng)耳迷走神經(jīng)電刺激適應癥之緩解偏頭痛
    巴林右旗| 佛教| 宁国市| 无极县| 廉江市| 蓝田县| 昌江| 司法| 新巴尔虎左旗| 姜堰市| 宁晋县| 类乌齐县| 渭源县| 台中县| 广南县| 南通市| 莱西市| 陇西县| 许昌县| 二连浩特市| 新野县| 红河县| 建平县| 永州市| 石屏县| 长岭县| 城步| 宁海县| 锡林郭勒盟| 民乐县| 沁阳市| 定南县| 呼图壁县| 平遥县| 黔南| 东兰县| 嵩明县| 东丰县| 喀什市| 新龙县| 读书|