1. 程式人生 > 其它 >二叉樹中最大搜索子樹和最大搜索子結構

二叉樹中最大搜索子樹和最大搜索子結構

技術標籤:Leetcode資料結構

最大的搜尋子樹


輸入描述:
第一行輸入兩個整數 n 和 root,n 表示二叉樹的總節點個數,root 表示二叉樹的根節點。
以下 n 行每行三個整數 fa,lch,rch,表示 fa 的左兒子為 lch,右兒子為 rch。(如果 lch 為 0 則表示 fa 沒有左兒子,rch同理)

ps:節點的編號就是節點的值。

輸入
3 2
2 1 3
1 0 0
3 0 0
輸出
3

基本思路

研究root開頭的子樹是否滿足二叉搜尋樹,滿足那麼直接返回root的大小
否則開始研究root的左右孩子所在子樹。

採取中序遍歷的方式,可以判斷二叉樹是否為搜尋樹,=》滿足升序

程式碼實現

#include<iostream>
#include<vector>
#include<stack>
using namespace std;
int ans=0;
bool judge(vector<int>&L,vector<int>&R,int root)
{

 
    //判斷是否為二叉搜尋樹
    
    int pre=0;
    stack<int> stk;
    int p=root;
    while(stk.empty()==false || p!=0)  //中序遍歷
    {
        if(p!=0)
        {
            stk.push(p);
            p=L[p];
        }
        else
        {
            int now=stk.top();
            stk.pop();
            if(now<pre) //不滿足
            {
                return false;
            }
            pre=now;
            p=R[now];
            
        }
    }
    return true; 
}
int add(vector<int>&L,vector<int>&R,int root)
{
    if(root==0)
        return 0;
    else
        return 1+add(L,R,L[root])+add(L,R,R[root]);
}
void dfs(vector<int>&L,vector<int>&R,int root)
{
    //首先研究root所在的樹是否滿足要求
    if(root==0)
        return;
    if(judge(L,R,root))  //滿足要求
    {
        ans=max(ans,add(L,R,root));
        return;//不需要再研究子樹
    }
    dfs(L,R,L[root]);
    dfs(L,R,R[root]);   
}
int main()
{
    int n,root;
    cin>>n>>root;
    vector<int> L(n+1);
    vector<int> R(n+1);
    for(int i=0;i<n;i++)
    {
        int fa,lc,rc;
        cin>>fa>>lc>>rc;
        L[fa]=lc;
        R[fa]=rc;
    }
    dfs(L,R, root);
    cout<<ans<<endl;
}

尋找二叉樹中最大搜索子結構

與最大搜索子樹不同,最大子結構可以挑選其中若干的點,使其滿足二叉搜尋樹即可

其特點為,最終樹一定有一個根節點root,那麼問題可以劃歸為在root中尋找,在root的左右子節點中尋找。

首先關鍵函式是研究以root為根節點的最大搜索拓撲結構

//研究node節點是否在以root為根節點的子樹中
bool isBSTNode(vector<int>&L,vector<int>&R,int root,int node)
{
    if(root==0)
        return false;
    if(root==node)
        return true;
    if(node>root)
        return isBSTNode(L,R,R[root], node);
    else
        return isBSTNode(L,R,L[root], node);
}

//研究以root祖先節點,cur為根節點的cur的最大搜索子結構

int getSize(vector<int>&L,vector<int>&R,int root,int cur)  //注意cur表示當前節點
{
    if(root==0 || cur==0)
        return 0;
    if(!isBSTNode(L,R,root,cur))  //並不在樹木中
        return 0;
    return 1+getSize(L,R, root,L[cur])+getSize(L,R, root,R[cur]);  //否則當前節點+左子樹節點最大+右子樹節點最大

}

其關鍵實現為研究一個節點node是否在root開始的搜尋樹結構中。

最終的遞迴函式如下:

void getMax(vector<int>&L,vector<int>&R,int root,int& ans)
{
    if(root==0)
        return;
    ans=max(ans,getSize(L,R,root,root));   
    getMax(L, R, L[root],ans);
     getMax(L, R, R[root],ans);
    
    
}

int main()
{
    int n,root;
    cin>>n>>root;
    vector<int> L(n+1);
    vector<int> R(n+1);
    for(int i=0;i<n;i++)
    {
        int fa,lc,rc;
        cin>>fa>>lc>>rc;
        L[fa]=lc;
        R[fa]=rc;
    }
    int ans=1;
    getMax(L, R, root, ans);
    cout<<ans<<endl;
    
    
}