地址:
力扣https://leetcode-cn.com/problems/path-in-zigzag-labelled-binary-tree/
题目:
在一棵无限的二叉树上,每个节点都有两个子节点,树中的节点 逐行 依次按 “之” 字形进行标记。
如下图所示,在奇数行(即,第一行、第三行、第五行……)中,按从左到右的顺序进行标记;
而偶数行(即,第二行、第四行、第六行……)中,按从右到左的顺序进行标记。
给你树上某一个节点的标号 label,请你返回从根节点到该标号为 label 节点的路径,该路径是由途经的节点标号所组成的。
示例 1:
输入:label = 14
输出:[1,3,4,14]
示例 2:
输入:label = 26
输出:[1,2,6,10,26]
提示:
1 <= label <= 10^6
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/path-in-zigzag-labelled-binary-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:
对于满二叉树,每一个节点都可以对应一个二进制数
示例:num = 14
需要经过的路径为: 14->4->3->1
如果是正常的应该 走灰色路径,毕竟存在 2x, 2x+1 的关系
目前正好父节点是镜像关系,我们来看看如何通过二进制计算出镜像节点值
1. 子节点依旧存在 /2 = 父节点 的关系,所以通过 14 >> 1 的到正常 7
2. 观察 7 与 4 镜像关系,可见除了最高位不变,其余位取反
3. 4 >> 1 往上层走,依旧存在最高位不变,其余位取反关系
4. 3 >> 1 = 1 到达根节点,结束
所以我们寻路逻辑就是右移,保持最高位,然后取反 ,一直循环直到根节点
方法一、二进制位操作
1. 首先要计算出 10 进制数总共有多少位
2. 取二进制末尾 k 位的公式: num &= 1<<k - 1
k 的左移后 - 1 相当于 1 移动到 k+1 位,然后 -1,保证 k 位全为 1
int countBit(int num)
{
int bits = 0;
while(num != 0)
{
bits++;
num >>= 1;
}
return bits;
}
int calNumbyBit(num, bits)
{
num &= ( ( (1<<(bits-1) ) - 1) );
num = ~num;
num &= ( (1<<bits) - 1);
return num;
}
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* pathInZigZagTree(int label, int* returnSize){
int bits = countBit(label);
int *arr = (int *)malloc(sizeof(int) * bits);
*returnSize = bits;
int i = bits -1;
while(label != 1)
{
arr[i] = label;
label >>= 1;
bits--;
label = calNumbyBit(label, bits);
i--;
}
arr[i] = label;
return arr;
}