二叉樹專題
阿新 • • 發佈:2022-03-20
之前學二叉樹的時候不認真,昨天遇到打比賽遇到一個二叉樹的板子題,沒做出來,所以就想重新鞏固一下
不過還好進我們學校的ACM的校隊了
考慮什麼情況下前後序都定下來的時候,但中序沒定
前序:根節點+左子樹+右子樹..........(1)
後序:左子樹+右子樹+根節點...........(2)
中序:左子樹+根節點+右子樹
規律有點點難找:
如果該節點只有一個兒砸,那麼這個兒砸無論是在左邊還是右邊
都不會改變前後序的排布
但是中序相應的肯定就會變化了
問題轉化為找到只有一個兒砸的結點就行了
根據(1)(2)發現
只要前序出現AB後序出現BA,那麼A就是隻有一個兒砸了
點選檢視程式碼
#include<bits/stdc++.h> using namespace std; #define lowbit(x) x&(-x) #define ll long long char s1[500],s2[500]; ll ans; int main(){ cin>>s1;cin>>s2; int len1=strlen(s1),len2=strlen(s2); for(int i=0;i<len1;i++) for(int j=1;j<len2;j++) if(s1[i]==s2[j]&&s1[i+1]==s2[j-1]) ans++; cout<<(1<<ans)<<endl; return 0; }
考慮直接遞迴判斷,對每個結點進行判斷,因為是二叉樹,所以複雜度為nlogn
點選檢視程式碼
#include<bits/stdc++.h> using namespace std; struct node{long long l,r,val;}bt[1000002]; bool same(long long now1,long long now2){//判斷是否對稱 if(now1==-1&&now2==-1) return true; if(now2==-1||now1==-1) return false;//小技巧 if(bt[now1].val!=bt[now2].val) return false; return same(bt[now1].l,bt[now2].r)&&same(bt[now1].r,bt[now2].l);//遞迴的判斷左右子樹相等 } int count(long long now){//遞迴的對左右子樹計數 return now==-1?0:count(bt[now].l)+count(bt[now].r)+1; } int main(){ int n,ans=0;cin>>n; for(int i=1;i<=n;i++) cin>>bt[i].val; for(int i=1;i<=n;i++) cin>>bt[i].l>>bt[i].r; for(int i=1;i<=n;i++)/*列舉每棵子樹*/ if(same(i,i)) ans=max(ans,count(i)); return 0&printf("%d",ans); }
考試就是這道模板型的題目,把我考住了
就是一道模板題
唯一要注意的點就是:因為要鏡面翻轉,所以先遍歷右子樹就好了
點選檢視程式碼
#include<bits/stdc++.h> using namespace std; #define lowbit(x) x&(-x) #define ll long long int mid[33];//zhong int pre[33];//qian int ans[125]; int n; void dfs(int u,int midl,int midr,int k){ if(midl>midr)return; int pos; for(int i=midl;i<=midr;i++){ if(mid[i]==pre[u]) pos=i; } ans[k]=pre[u]; dfs(u+pos-midl+1,pos+1,midr,k*2); dfs(u+1,midl,pos-1,k*2+1); } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&mid[i]); for(int i=1;i<=n;i++)scanf("%d",&pre[i]); dfs(1,1,n,1); int cnt=0; for(int i=1;i<=124;i++){ if(ans[i]) cout<<ans[i],cnt++; if(cnt<n&&ans[i])cout<<" "; } return 0; }