求整顆二叉樹的最大搜尋二叉子樹
邏輯:將整個題目轉成以每個節點作為頭的最大搜尋二叉子樹,最大的搜尋二叉子樹一定在其中。基本二叉樹的題目都可以利用這樣的思想進行求解。
思路:當前節點的最大搜尋子樹可能來自於
左子樹的某個子樹,
右子樹的某個子樹,
左子樹是搜尋二叉樹,右子樹也是搜尋二叉樹,並且左子樹的最大值小於我,右子樹的最小值大於我,則以我為頭為整個搜尋二叉子樹
主邏輯:對每個節點進行上述的分析
詳細點:子樹如何進行判斷上述的過程,需要蒐集哪些資訊。
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...