(完全二叉树编号)小球下落
題目
有一棵二叉樹(shù),最大深度為D,且所有的葉子深度都相同。所有結(jié)點(diǎn)從上到下從左到右編號(hào)為1,2,3,…,2eD-1。在結(jié)點(diǎn)1處放一個(gè)小球,它會(huì)往下落。每個(gè)結(jié)點(diǎn)上都有一個(gè)開(kāi)關(guān),初始全部關(guān)閉,當(dāng)每次有小球落到一個(gè)開(kāi)關(guān)上時(shí),它的狀態(tài)都會(huì)改變。當(dāng)小球到達(dá)一個(gè)內(nèi)結(jié)點(diǎn)時(shí),如果該結(jié)點(diǎn)的開(kāi)關(guān)關(guān)閉,則往上走,否則往下走,直到走到葉子結(jié)點(diǎn),如下圖所示。
一些小球從結(jié)點(diǎn)1處依次開(kāi)始下落,最后一個(gè)小球?qū)?huì)落到哪里呢?輸入葉子深度D和小球個(gè)數(shù)I,輸出第I個(gè)小球最后所在的葉子編號(hào)。假設(shè)I不超過(guò)整棵樹(shù)的葉子數(shù);D<=20。輸出最多包含1000組數(shù)據(jù)。
樣例輸入:
4 2
3 4
10 1
2 2
8 128
16 12345
樣例輸出:
12
7
512
3
255
36358
分析與解答
<0>.給定一顆2^d個(gè)結(jié)點(diǎn)的完全二叉樹(shù),如果把結(jié)點(diǎn)從上到下從左到右編號(hào),則結(jié)點(diǎn)k的左右子結(jié)點(diǎn)編號(hào)分別為2k,2k+1
<1>.根據(jù)觀察,對(duì)于根結(jié)點(diǎn),小球編號(hào)為奇數(shù)落在左子樹(shù),偶數(shù)落在右子樹(shù)
<2>.每個(gè)節(jié)點(diǎn)都可以看成根結(jié)點(diǎn),并且與他兩個(gè)子結(jié)點(diǎn)組成一個(gè)新的二叉樹(shù)
<3>.根據(jù)根結(jié)點(diǎn)1,找規(guī)律發(fā)現(xiàn),如果小球編號(hào)為奇數(shù),他是往左走的第(i+1)/2個(gè)小球,如果小球編號(hào)為偶數(shù),他是往右走的第i/2個(gè)小球。
<4>.如果把每個(gè)子節(jié)點(diǎn)看成一個(gè)根結(jié)點(diǎn),那么每個(gè)結(jié)點(diǎn)的小球也滿足3的規(guī)律
<5>.第i個(gè)小球,從結(jié)點(diǎn)編號(hào)為k的地方下落,如果i為奇數(shù),那么此時(shí)等價(jià)于第(i+1)/2個(gè)小球,從結(jié)點(diǎn)編號(hào)為k*2的地方下落,如果i為偶數(shù),那么此時(shí)等價(jià)于第i/2個(gè)小球,從結(jié)點(diǎn)編號(hào)為k*2+1的地方下落,然后通過(guò)<1>,我們就知道他下一步是向左還是向右走
<6>.二叉樹(shù)深度為d,小球下落d-1次,每循環(huán)一次,我們就知道他落在哪,下一步怎么走,如果循環(huán)d-1次,剛好走到最后的葉子結(jié)點(diǎn),此時(shí)知道他落在哪,輸出k就行
代碼:
#include<cstdio>int main(){int d,I;while(scanf("%d%d",&d,&I)==2){int k=1;for(int i=0;i<d-1;++i){if(I%2){k=k*2;I=(I+1)/2;}else {k=k*2+1;I/=2;}}printf("%d\n",k);} }方法二:
利用模擬,二叉樹(shù)編號(hào)
總結(jié)
以上是生活随笔為你收集整理的(完全二叉树编号)小球下落的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: oracle11g基目录和主目录,Red
- 下一篇: 类和对象提高