一、问题描述
在一棵无限的二叉树上,每个节点都有两个子节点,树中的节点 逐行 依次按 “之” 字形进行标记。
如下图所示,在奇数行(即,第一行、第三行、第五行……)中,按从左到右的顺序进行标记;
而偶数行(即,第二行、第四行、第六行……)中,按从右到左的顺序进行标记。
给你树上某一个节点的标号 label
,请你返回从根节点到该标号为 label
节点的路径,该路径是由途经的节点标号所组成的。
?
二、测试数据
示例 1:
输入:label = 14
输出:[1,3,4,14]
示例 2:
输入:label = 26
输出:[1,2,6,10,26]
提示:
1 <= label <= 10^6
?
三、解题思路
? 利用 偶不变,奇变 将路径从目标逐渐向根节点求解,结果倒置即可(2^0 ~ 2^layer)
存储由于是倒置的,可利用 栈(ArrayDeque) 或 数组(数组个数和数组顺序已确定,个数为 layer+1
)
经研究得数组所使用内存较小,故使用数组
解题步骤:
- 先求层数
layer
:根据完全二叉树每棵树节点数都为 2^n - 将路径从目标逐渐向根节点求解:
- 若层数为偶不变,为奇则转换为对称点(由数学得对称点为
truth = 3*(int)Math.pow(2,exp) -1 - label
) - 求完正确值
truth
,转为父节点求解(label = label/2
)此时不考虑转换,因为正确值会转换 - 交换转换
isChange = !isChange
- 若层数为偶不变,为奇则转换为对称点(由数学得对称点为
//具体循环如下:for(int exp = layer,truth = 0;exp>=0;exp--){
if(isChange){
truth = 3*(int)Math.pow(2,exp) -1 - label;}else{
truth = label;}if(exp!= layer){
number[exp] = truth;} label = label/2; isChange = !isChange; }
?
四、java实现
class Solution {
public List<Integer> pathInZigZagTree(int label) {
List<Integer> result = new ArrayList<>();if(label == 1){
result.add(1); }else{
int layer = 0;for(int number = label;;layer++){
number -= (int)Math.pow(2,layer);if(number <= 0){
break;} }int[] number = new int[layer+1];number[layer] = label;boolean isChange = false;//偶数不变for(int exp = layer,truth = 0;exp>=0;exp--){
if(isChange){
truth = 3*(int)Math.pow(2,exp) -1 - label;}else{
truth = label;}if(exp!= layer){
number[exp] = truth;} label = label/2; isChange = !isChange; }for(int num:number){
result.add(num);} }return result;}
}