完全二叉树的算法问题

时间:2018-09-01 23:41:39

标签: algorithm binary-tree

已知最大深度为16的完整二叉树,所有叶节点的深度相同。如果在根节点上放置一个小球,则该球将开始沿根节点掉落。完整的二叉树中的每个节点上都有一个开关。默认为关闭。当球落下时,只要球落在开关上,开关的状态就会改变。当球到达某个节点时,如果该节点上的开关闭合,则向左转到该球,否则向右转到直到到达叶子节点。请帮助我找到第12345个球掉落后的叶子节点编号。

1 个答案:

答案 0 :(得分:1)

您可以模拟一个给定的问题,并注意到在一个时间点之后,球末端的叶子节点趋向于重复自身。例如,对于深度为3的二叉树,多个滚动球的球结束处的叶节点为1 3 2 4 1 3 2 4 1 3 2 4 . . .假设叶节点的编号从1 开始)。可见,长度2 3-1 = 4的序列不断重复。我们可以将该序列存储在数组中,并通过查找与 n mod 2 depth-1 <相对应的条目来回答第n个球的查询。 / em>该数组中的索引。

由于我们的深度达到16,所以生成重复序列所需的操作总数为2 16-1 * 16 = 524288个操作。

为相同的https://ideone.com/uuNV2g共享代码

#include <iostream>
#include <map>
#include <vector>
using namespace std;

map<int, bool> states; // default value is False
int MAX_DEPTH = 16;

int dfs(int cur, int depth = 0) {
    if(depth == MAX_DEPTH) {
        return cur - (1<<MAX_DEPTH) + 1;
    }

    if(states[cur] == 0) {
        states[cur] = !states[cur];
        return dfs(2*cur, depth+1);
    }
    else {
        states[cur] = !states[cur];
        return dfs(2*cur+1, depth+1);
    }

}

int main() {
    int until = (1LL<<(MAX_DEPTH-1));
    vector<int> pos; // 0 indexed
    for(int i = 1; i <= until; i++) {
        // cout << dfs(1) << ' ';
        pos.push_back(dfs(1));
    }

    cout << pos[(12344%until)]; 
    // 12344 instead of 12345 since the sequence is 0 indexed
}

希望它能解决。