欧美性猛交xxxx免费看_牛牛在线视频国产免费_天堂草原电视剧在线观看免费_国产粉嫩高清在线观看_国产欧美日本亚洲精品一5区

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

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

一個(gè)數(shù)據(jù)結(jié)構(gòu)-線(xiàn)段樹(shù)

算法與數(shù)據(jù)結(jié)構(gòu) ? 來(lái)源:算法與數(shù)據(jù)結(jié)構(gòu) ? 2020-05-06 11:02 ? 次閱讀

一、概念解析

這次來(lái)介紹一個(gè)數(shù)據(jù)結(jié)構(gòu) - 線(xiàn)段樹(shù)。

在平時(shí)刷題或是工作中,經(jīng)常會(huì)遇到這么一個(gè)問(wèn)題,“給定一個(gè)數(shù)組,求出數(shù)組某段區(qū)間的一些性質(zhì)”。

比如給定一個(gè)數(shù)組 [5,2,6,1,-4,0,9,2],讓你求出區(qū)間 [1,4] 上所有元素的和,在這個(gè)例子中,答案是 2 + 6 + 1 + (-4) = 5。

你可能會(huì)說(shuō),直接遍歷一遍不就好了嗎?

最簡(jiǎn)單的方式就是直接遍歷一遍區(qū)間,時(shí)間復(fù)雜度也顯而易見(jiàn) O(n),如果在這個(gè)數(shù)組上頻繁進(jìn)行這個(gè)操作,那么效率相對(duì)來(lái)說(shuō)會(huì)比較低,怎么優(yōu)化呢?

對(duì)于求區(qū)間和的問(wèn)題,前綴和數(shù)組是一個(gè)不錯(cuò)的選擇,構(gòu)建好前綴和數(shù)組后,求一個(gè)區(qū)間和的話(huà)只要前后一減就可以了,如果不算構(gòu)建數(shù)組的時(shí)間,那么每次的操作時(shí)間復(fù)雜度就是 O(1)。

這里的問(wèn)題在于前綴和數(shù)組只能解決求區(qū)間和的問(wèn)題,但是其他的區(qū)間問(wèn)題,前綴和數(shù)組并不能很好的解決,比如求某段區(qū)間上的最大值。

因此我們需要一個(gè)數(shù)據(jù)結(jié)構(gòu)能夠幫助我們解決大部分?jǐn)?shù)組的區(qū)間問(wèn)題,而且時(shí)間復(fù)雜度要盡可能的低。

這也就是今天的主題 - 線(xiàn)段樹(shù),首先要說(shuō)明一點(diǎn)的是,線(xiàn)段樹(shù)也是二叉樹(shù),只是它的節(jié)點(diǎn)里面含有區(qū)間的信息。

線(xiàn)段樹(shù)每個(gè)節(jié)點(diǎn)表示的是一個(gè)區(qū)間,每個(gè)節(jié)點(diǎn)將其表示的區(qū)間一分為二,左邊分到左子樹(shù),右邊分到右子樹(shù),根節(jié)點(diǎn)表示的是整個(gè)區(qū)間(也就是整個(gè)數(shù)組),葉子節(jié)點(diǎn)表示的是一個(gè) index(也就是單個(gè)元素),因?yàn)槊看螌?duì)半分的緣故,線(xiàn)段樹(shù)構(gòu)建出來(lái)是平衡的,也就是說(shuō)樹(shù)的高度是 O(logn),這里的 n 表示的是數(shù)組中所有的元素,這一點(diǎn)對(duì)于我們后面分析復(fù)雜度很重要。

線(xiàn)段樹(shù)有三個(gè)基本的操作,分別是構(gòu)建線(xiàn)段樹(shù)(build)、區(qū)間查找(query)、還有就是修改(modify),假設(shè)我們現(xiàn)在需要解決的問(wèn)題是 “求區(qū)間上的最大值”,例子還是之前的例子,一起來(lái)看看怎么實(shí)現(xiàn)這些操作。

對(duì)于構(gòu)建操作來(lái)說(shuō),相對(duì)簡(jiǎn)單,你只需要記住 “自上而下而下遞歸分裂,自下而上回溯更新” 從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)我們不斷地將區(qū)間一分為二,從葉子節(jié)點(diǎn)開(kāi)始返回值,一直到根節(jié)點(diǎn),不斷地更新區(qū)間信息。

查找操作是線(xiàn)段樹(shù)的核心操作,考慮的情況相對(duì)較多,這里有四種情況:

情況一:節(jié)點(diǎn)區(qū)間包含查找區(qū)間。這種情況直接遞歸向下查找即可

情況二:節(jié)點(diǎn)區(qū)間不相交于查找區(qū)間。因?yàn)闆](méi)有要查找的范圍,停止搜索

情況三:節(jié)點(diǎn)區(qū)間相交但不包含查找區(qū)間。將區(qū)間分成兩段,分別查找

情況四:節(jié)點(diǎn)區(qū)間相等于查找區(qū)間。直接返回答案

說(shuō)明一下,這里說(shuō)的 “包含” 的意思是一個(gè)區(qū)間全部元素都被另外一個(gè)區(qū)間涵蓋,“相交” 的意思是一個(gè)區(qū)間的部分元素被另外一個(gè)區(qū)間涵蓋,例如要查找的區(qū)間是 [1,3],那么 [0,4] 包含要查找的區(qū)間,[2,5] 只是相交要查找的區(qū)間。對(duì)于區(qū)間查找,后面有圖解,跟著例子走一遍印象會(huì)更深刻。

最后一個(gè)修改操作,和構(gòu)建操作類(lèi)似,但有些許不同,你只需要記住 “自上而下遞歸查找,自下而上回溯更新”。修改的意思是,修改數(shù)組中的一個(gè)元素的值,這會(huì)影響相關(guān)的區(qū)間,相關(guān)的樹(shù)節(jié)點(diǎn),因此,相關(guān)聯(lián)的節(jié)點(diǎn)也就需要更新。

線(xiàn)段樹(shù)靈活的地方在于,樹(shù)節(jié)點(diǎn)中存放的數(shù)據(jù)不同,它的功能就不同,比如說(shuō),你想要求解區(qū)間和,那么樹(shù)節(jié)點(diǎn)中就存放對(duì)應(yīng)區(qū)間元素的和,你想求解區(qū)間上的最大值,那么樹(shù)節(jié)點(diǎn)中存放的就是對(duì)應(yīng)區(qū)間上的最大值。不過(guò)話(huà)說(shuō)回來(lái),線(xiàn)段樹(shù)并不是一個(gè)被廣泛應(yīng)用的數(shù)據(jù)結(jié)構(gòu),原因可能在于線(xiàn)段樹(shù)的構(gòu)建和使用相對(duì)于前綴和數(shù)組這樣的技巧來(lái)說(shuō),稍微復(fù)雜了些。但是在解決數(shù)組區(qū)間的問(wèn)題上,線(xiàn)段樹(shù)可以提供一個(gè)還不錯(cuò)的思考方向。

二、動(dòng)畫(huà)描述

三、代碼實(shí)現(xiàn)

publicclassSolution{ privateclassSegmentTreeNode{ intstart,end,max; SegmentTreeNodeleft,right; SegmentTreeNode(intstart,intend,intmax){ this.start=start; this.end=end; this.max=max; this.left=this.right=null; } } publicSegmentTreeNodebuild(intstart,intend,int[]nums){ if(start>end){ returnnull; } if(start==end){ returnnewSegmentTreeNode(start,end,nums[start]); } SegmentTreeNodenode=newSegmentTreeNode(start,end,nums[start]); //自上而下而下遞歸分裂 if(start!=end){ intmid=(start+end)/2; node.left=build(start,mid,nums); node.right=build(mid+1,end,nums); } //自下而上回溯更新 if(node.left!=null&&node.left.max>node.max){ node.max=node.left.max; } if(node.right!=null&&node.right.max>node.max){ node.max=node.right.max; } returnnode.max; } publicintquery(SegmentTreeNoderoot,intstart,intend){ //如果節(jié)點(diǎn)區(qū)間相等于查找區(qū)間,直接返回對(duì)應(yīng)的值即可 if(root.start==start&&root.end==end){ returnroot.max; } intmid=(root.start+root.end)/2; intleftMax=Integer.MIN_VALUE,rightMax=Integer.MIN_VALUE; //判斷是否需要去左子樹(shù)查找 if(start<=?mid)?{ ????????????//?節(jié)點(diǎn)相交查找區(qū)間的情況 ????????????if?(end?>mid){ leftMax=query(root.left,start,mid); }//節(jié)點(diǎn)包含查找區(qū)間的情況 else{ leftMax=query(root.left,start,end); } } //判斷是否需要去右子樹(shù)查找 if(mid=root.end){ return; } //自上而下遞歸查找 modify(root.left,index,value); modify(root.right,index,value); //自下而上回溯更新 root.max=Math.max(root.left.max,root.right.max); } }

四、復(fù)雜度分析

三個(gè)操作中,構(gòu)建樹(shù)的操作的時(shí)間復(fù)雜度是 O(n),原因也很好解釋?zhuān)瑯?gòu)建的樹(shù)有 2n 個(gè)節(jié)點(diǎn),你可能會(huì)問(wèn)這個(gè) 2n 是怎么得到的,思考這個(gè)問(wèn)題可以從葉子節(jié)點(diǎn)出發(fā),一共有 n 個(gè)葉子節(jié)點(diǎn),構(gòu)建操作是從上往下不斷二分,這樣保證了樹(shù)的平衡,因此所有節(jié)點(diǎn)個(gè)數(shù)就是 n + n/2 + n/4 + ... + 1 = 2n。

由于構(gòu)建每個(gè)節(jié)點(diǎn)只花了 O(1) 的時(shí)間,因此整個(gè)構(gòu)建的時(shí)間復(fù)雜度就是 O(2n),忽略常數(shù)項(xiàng),也就是 O(n)。

修改和查找都是沿著一條或者幾條從上到下的路徑進(jìn)行的,因?yàn)闃?shù)的高度是 O(logn),所以這兩個(gè)操作的時(shí)間復(fù)雜度也是 O(logn)??梢钥吹竭@個(gè)時(shí)間復(fù)雜度比暴力的 O(n) 還是快不少。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴

原文標(biāo)題:什么是線(xiàn)段樹(shù)?

文章出處:【微信號(hào):TheAlgorithm,微信公眾號(hào):算法與數(shù)據(jù)結(jié)構(gòu)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    如何把兩個(gè)數(shù)據(jù)返回給調(diào)用函數(shù)

    函數(shù)的處理結(jié)果包含兩個(gè)數(shù)據(jù),如何把兩個(gè)數(shù)據(jù)返回給調(diào)用函數(shù)? 第種,把兩個(gè)數(shù)據(jù)封裝成個(gè)
    的頭像 發(fā)表于 01-08 10:15 ?106次閱讀

    嵌入式學(xué)習(xí)-飛凌嵌入式ElfBoard ELF 1板卡-初識(shí)設(shè)備樹(shù)之設(shè)備樹(shù)組成和結(jié)構(gòu)

    項(xiàng)技能。設(shè)備樹(shù)的起源設(shè)備樹(shù)(Device Tree)是種描述硬件資源的數(shù)據(jù)結(jié)構(gòu),它由uboot傳遞給Linux內(nèi)核,被內(nèi)核解析,內(nèi)核根
    發(fā)表于 01-08 08:32

    飛凌嵌入式ElfBoard ELF 1板卡-初識(shí)設(shè)備樹(shù)之設(shè)備樹(shù)組成和結(jié)構(gòu)

    項(xiàng)技能。設(shè)備樹(shù)的起源設(shè)備樹(shù)(Device Tree)是種描述硬件資源的數(shù)據(jù)結(jié)構(gòu),它由uboot傳遞給Linux內(nèi)核,被內(nèi)核解析,內(nèi)核根
    發(fā)表于 01-07 09:16

    DDC264配置寄存器數(shù)據(jù)寫(xiě)入和320 DCLK時(shí)鐘脈沖后的回讀數(shù)據(jù)結(jié)構(gòu)是什么?

    配置寄存器數(shù)據(jù)寫(xiě)入和320 DCLK時(shí)鐘脈沖后的回讀數(shù)據(jù)結(jié)構(gòu)是什么? 根據(jù)注和表9,16位配置寄存器數(shù)據(jù),4位修訂ID, 300位校驗(yàn)?zāi)J?,怎么可能?024 TOTAL READBACK BITS, format = 0
    發(fā)表于 11-19 07:58

    視覺(jué)軟件HALCON的數(shù)據(jù)結(jié)構(gòu)

    在研究機(jī)器視覺(jué)算法之前,我們需要先了解機(jī)器視覺(jué)應(yīng)用中涉及的基本數(shù)據(jù)結(jié)構(gòu)。Halcon數(shù)據(jù)結(jié)構(gòu)主要有圖像參數(shù)和控制參數(shù)兩類(lèi)參數(shù)。圖像參數(shù)包括:image、region、XLD,控制參數(shù)包括:string、integer、real、handle、tuple數(shù)組等。
    的頭像 發(fā)表于 11-14 10:20 ?568次閱讀
    視覺(jué)軟件HALCON的<b class='flag-5'>數(shù)據(jù)結(jié)構(gòu)</b>

    什么是默克爾樹(shù)(Merkle Tree)?如何計(jì)算默克爾根?

    01 默克爾樹(shù)的概念 默克爾樹(shù)(Merkle Tree)是種特殊的二叉樹(shù),它的每個(gè)節(jié)點(diǎn)都存儲(chǔ)了個(gè)數(shù)據(jù)
    的頭像 發(fā)表于 09-30 18:22 ?1110次閱讀
    什么是默克爾<b class='flag-5'>樹(shù)</b>(Merkle Tree)?如何計(jì)算默克爾根?

    嵌入式常用數(shù)據(jù)結(jié)構(gòu)有哪些

    在嵌入式編程中,數(shù)據(jù)結(jié)構(gòu)的選擇和使用對(duì)于程序的性能、內(nèi)存管理以及開(kāi)發(fā)效率都具有重要影響。嵌入式系統(tǒng)由于資源受限(如處理器速度、內(nèi)存大小等),因此對(duì)數(shù)據(jù)結(jié)構(gòu)的選擇和使用尤為關(guān)鍵。以下是嵌入式編程中常用的幾種數(shù)據(jù)結(jié)構(gòu),結(jié)合具體特點(diǎn)和
    的頭像 發(fā)表于 09-02 15:25 ?629次閱讀

    20個(gè)數(shù)據(jù)可以訓(xùn)練神經(jīng)網(wǎng)絡(luò)嗎

    當(dāng)然可以,20個(gè)數(shù)據(jù)點(diǎn)對(duì)于訓(xùn)練個(gè)神經(jīng)網(wǎng)絡(luò)來(lái)說(shuō)可能非常有限,但這并不意味著它們不能用于訓(xùn)練。實(shí)際上,神經(jīng)網(wǎng)絡(luò)可以訓(xùn)練在非常小的數(shù)據(jù)集上,但需要采取
    的頭像 發(fā)表于 07-11 10:29 ?1132次閱讀

    原理圖設(shè)計(jì)里兩顆重要的樹(shù)(國(guó)產(chǎn)EDA)

    原理圖里面兩顆重要的樹(shù),那就是元件樹(shù)和網(wǎng)絡(luò)樹(shù),作為EDA工具中的重要視圖和概念,雖然看似枯燥,但它們扮演著非常重要的角色,它們?yōu)殡娐穲D的層次化結(jié)構(gòu)提供了有力支撐。想象
    的頭像 發(fā)表于 05-29 17:47 ?832次閱讀
    原理圖設(shè)計(jì)里兩顆重要的<b class='flag-5'>樹(shù)</b>(國(guó)產(chǎn)EDA)

    STM32F0xx_HAL_Driver庫(kù)的串口接收數(shù)據(jù)個(gè)數(shù),是不是只能寫(xiě)成1,一個(gè)一個(gè)數(shù)據(jù)接收?

    ,uint8_t *pData, uint16_tSize, uint32_tTimeout ) 函數(shù)的第三個(gè)參數(shù)是接收數(shù)據(jù)個(gè)數(shù)。 問(wèn)題是: 如果不知道接收數(shù)據(jù)
    發(fā)表于 05-14 06:39

    STM32F429如何次傳3000個(gè)數(shù)據(jù)

    正點(diǎn)原子的歷程中實(shí)用的是8位的數(shù)據(jù)傳輸,也就是說(shuō)最多次能傳255個(gè)數(shù)據(jù),我要是次想傳3000個(gè)數(shù)據(jù),應(yīng)該怎么更給程序?
    發(fā)表于 05-11 08:56

    揭秘編程核心:基本數(shù)據(jù)結(jié)構(gòu)與算法思想詳解

    描述問(wèn)題的數(shù)據(jù)除了各數(shù)據(jù)元素本身,還要考慮各元素的邏輯關(guān)系,主要是一對(duì)一的線(xiàn)性關(guān)系,對(duì)多的樹(shù)型關(guān)系和多對(duì)多的圖形關(guān)系。
    的頭像 發(fā)表于 04-25 11:51 ?1169次閱讀
    揭秘編程核心:基本<b class='flag-5'>數(shù)據(jù)結(jié)構(gòu)</b>與算法思想詳解

    探索編程世界的七大數(shù)據(jù)結(jié)構(gòu)

    樹(shù)結(jié)構(gòu)就像是顆倒掛的小樹(shù),有根、有枝、有葉。它是種非線(xiàn)性的數(shù)據(jù)結(jié)構(gòu),以層級(jí)的方式存儲(chǔ)數(shù)據(jù),頂部是根節(jié)點(diǎn),底部是葉節(jié)點(diǎn)。
    的頭像 發(fā)表于 04-16 12:04 ?436次閱讀

    TASKING編譯器是否可以將數(shù)據(jù)結(jié)構(gòu)設(shè)置為 \"打包\"?

    TASKING 編譯器是否可以將數(shù)據(jù)結(jié)構(gòu)設(shè)置為 \"打包\"? GCC 很早以前就提供了這種可能性,可以將__attribute__((packed))與對(duì)齊指令結(jié)合使用。 對(duì)于
    發(fā)表于 03-05 06:00

    矢量與柵格數(shù)據(jù)結(jié)構(gòu)各有什么特征

    數(shù)據(jù)結(jié)構(gòu)是使用點(diǎn)、線(xiàn)和面等基本幾何圖形來(lái)描述和表示地理對(duì)象的種方法。它們由離散的幾何對(duì)象和與之相關(guān)的屬性數(shù)據(jù)組成。矢量數(shù)據(jù)中的點(diǎn)表示
    的頭像 發(fā)表于 02-25 15:06 ?2784次閱讀