左神演算法筆記(十九) 樹型DP(動態規劃)

2021-10-02 16:11:29 字數 4063 閱讀 4772

求整顆二叉樹的最大搜尋二叉子樹

邏輯:將整個題目轉成以每個節點作為頭的最大搜尋二叉子樹,最大的搜尋二叉子樹一定在其中。基本二叉樹的題目都可以利用這樣的思想進行求解。

思路:當前節點的最大搜尋子樹可能來自於

左子樹的某個子樹,

右子樹的某個子樹,

左子樹是搜尋二叉樹,右子樹也是搜尋二叉樹,並且左子樹的最大值小於我,右子樹的最小值大於我,則以我為頭為整個搜尋二叉子樹

主邏輯:對每個節點進行上述的分析

詳細點:子樹如何進行判斷上述的過程,需要蒐集哪些資訊。

1. 左樹最大搜尋二叉樹大小,頭部

2. 右部最大搜尋二叉樹大小,頭部

3. 左樹上的最大值

4. 右樹上的最小值

有了以上的資訊,則可以計算出上述的三種情況。

因為整個資訊會在遞迴中展示,所以需要將上述訊息體進行整合

1. 搜大小

2. 搜頭部

3. 當前樹最大

4. 當前樹最小

上述三點為精簡後的訊息體,對於左邊還是右邊,最後上傳的內容體都相同,不區分左右。這樣會更加具有普遍性,此時可以進行遞迴,從而實現演算法。

遞迴的整個過程:

1. 明確可能性情況

2. 明確需要的引數內容

3. 將引數當做黑盒對待,假設下面的節點可以直接返回該形式,改遞迴。

4. 將可能性分別列出

5. 將黑盒展開,明確當前節點需要返回的內容,編寫**實現。

//首先明確好返回值的型別,都需要返回的內容

public

static

class

returntype

}//遞迴的整個過程,按照上述所分的三種可能進行分析

public

static returntype process

(node head)

//明確好需要返回的值,此時相信左子樹和右子樹會給我我想要的內容。遞迴形式在這裡確立

node left = head.left;

returntype leftsubtreessinfo =

process

(left);

node right = head.right;

returntype rightsubtreessinfo =

process

(right)

;int includeitself =0;

//如果滿足下面的if判斷,則意味著包含當前節點可以形成搜尋二叉樹

if(leftsubtreessinfo.head == left

&&rightsubtreessinfo.head ==right

&&head.value > leftsubtreessinfo.max

&&head.value < rightsubtreessinfo.min

)//無論上面判斷是否成立,下面的**都將執行,確立遞迴中元素的值,下面分別確定maxsize,和maxhead。

int p1 = leftsubtreessinfo.size;

int p2 = rightsubtreessinfo.size;

int maxsize = math.

max(math.

max(p1,p2)

,includeitself);

node maxhead = p1 >p2 ? leftsubtreessinfo.head :rightsubtreessinfo.head;

if(maxsize == includeitself)

return

newreturntype

(maxsize,

maxhead,

math.

min(math.

min(leftsubtreessinfo.min,rightsubtreessinfo.min)

,head.value)

, math,

max(math.

max(leftsubtreessinfo.max,rightsubtreessinfo.max)

,head.value));

}

上述**就是描述了整個二叉樹遞迴的過程,確立好遞迴的思路,確立好遞迴需要的內容,之後編寫**實現遞迴的過程。此時時間複雜度還是o(n),每個節點僅遍歷一遍,就可以得到當前節點的對應資訊給父節點,不需要再遍歷,中間的過程資料傳輸的複雜度為o(1)。

情況分析:

1. 最大距離來自左子樹

2. 最大距離來自右子樹

3. 最大距離跟當前節點相關,則最大距離為左樹距離和右樹距離再加上自己這個點。

需要的資訊:

1. 左長距離

2. 右長距離

3. 左深+右深

整合之後的資訊:

1. 最長距離

2. 深度

//整合的資訊

public

static

class

returntype

}//遞迴整個流程

public

static returntype process

(node head)

returntype leftreturntype =

process

(head.left)

; returntype rightreturntype =

process

(head.right)

;int includeheaddistance = leftreturntype.h + rightreturntype.h;

int p1 = leftreturntype.maxdistance;

int p2 = rightreturntype.maxdistance;

int resultdistance = math.

max(math.

max(p1,p2)

,includeheaddistance)

;int hitself = math.

max(leftreturntype.h,rightreturntype.h)+1

;return

newreturntype

(resultdistance,hitself);}

//返回給主函式結果

同樣的情況,如果我可以求出每乙個節點子樹中最活躍的情況,則最後最活躍的情況一定包含在其中。

自己的分析

分情況:

1. 當前節點最活躍的情況包含當前節點,則它的子節點一定不在其中。活躍度為所有孫子節點的最大活躍度之和再加上當前節點的活躍度。

2. 當前節點最活躍的情況不包含當前節點,則他最活躍的情況是所有子樹最大活躍度之和。

需要的資訊:

1. 子節點的最大活躍度和

2. 孫子節點的最大活躍度和。

其實來的最大活躍度資訊對應著孫子節點的最大活躍度之和。不來的最大活躍度對應著子節點的最大活躍度之和。但是會涉及到孫子節點資訊,可能需要加額外的判斷。

左神的分析

分情況:

1. 最活躍包含當前節點,子節點一定不來,子節點不來的最大活躍度

2. 不包含當前節點,最大值為所有子節點來或不來中的最大值之和。

需要的資訊:

1. 來的最大活躍度

2. 不來的最大活躍度

public

static

class

returndata

}public

static returndata process

(node head)

return

newreturndata

(lai_huo,bulai_huo)

;

左神演算法學習日記 樹dp

樹dp問題只需要考慮每個結點的所有孩子的情況就可以解決 class node node class treeinf void creat node node if r 獲得子樹中結點最多的搜尋二叉樹的結點個數 treeinf getmaxnode node node treeinf leftinf ...

左神演算法講堂筆記 05 樹

非遞迴遍歷有點難,目前只能讀懂 裡面的精髓還未真正參透。先序遍歷 不斷地把根入棧,再取出來輸出 根左右,那麼先入棧的肯定是根,要保證輸出左子樹,再輸出右子樹,那麼就要先入棧右子樹。void preorderunrecur node head if node.left null 中序遍歷 必須左子樹走...

左神演算法筆記(九) 字首樹擴充

給定乙個陣列,求子陣列的最大異或和。乙個陣列的異或和為陣列中所有的數異或起來的結果。之前做個乙個找到異或和為0的最長子陣列,思路是將每乙個節點當做異或和的最後乙個節點,求解最長的子陣列。同樣這個題目可以以這種方法解決。以i位置結尾的最大異或和的值,最大的異或和一定包含在其中。暴力解法就是從0 i,1...