数组二叉树

一、题目描述

二叉树也可以用数组来存储,给定一个数组,树的根节点的值存储在下标1,对于存储在下标N的节点,它的左子节点和右子节点分别存储在下标2*N和2*N+1,并且我们用值-1代表一个节点为空。

给定一个数组存储的二叉树,试求从根节点到最小的叶子节点的路径,路径由节点的值组成。

二、输入输出描述

输入描述

输入一行为数组的内容,数组的每个元素都是正整数,元素间用空格分隔。

注意

  1. 第一个元素即为根节点的值,即数组的第N个元素对应下标N,下标0在树的表示中没有使用,所以我们省略了。
  2. 输入的树最多为7层。

输出描述

输出从根节点到最小叶子节点的路径上,各个节点的值,由空格分隔,用例保证最小叶子节点只有一个。

三、示例

|----|------------------|
| 输入 | 3 5 7 -1 -1 2 4 |
| 输出 | 3 7 2 |
| 说明 | 最小叶子节点的路径为3 7 2。 |

|----|------------------------------------------------------|
| 输入 | 5 9 8 -1 -1 7 -1 -1 -1 -1 -1 6 |
| 输出 | 5 8 7 6 |
| 说明 | 最小叶子节点的路径为5 8 7 6,注意数组仅存储至最后一个非空节点,故不包含节点"7"右子节点的-1。 |

四、解题思路

  1. 核心思想

先利用完全二叉树的数组存储规则识别所有叶子节点,找到值最小的那个;再通过 "子→父" 的索引关系回溯,拼接出从根到该叶子的路径 ------ 核心是 "先定位目标节点,再反向回溯路径"。

  1. 问题本质分析

问题本质是完全二叉树的叶子节点定位 + 路径回溯

  • 二叉树的数组存储是 "静态结构化" 的,节点间的父子关系可通过索引公式直接计算,无需构建树结构;
  • 核心需求分为两步:① 筛选叶子节点并找最小值;② 从目标叶子反向推导根节点,形成正向路径。
  1. 核心逻辑
  • 叶子节点判定:利用完全二叉树的索引规则,判断节点是否有有效子节点(无则为叶子);
  • 最小值筛选:遍历所有叶子节点,记录值最小的节点索引;
  • 路径回溯:通过父节点索引公式 (i-1)/2,从叶子节点向上遍历至根,按 "根→叶子" 的顺序拼接路径。
  1. 步骤拆解

  2. 输入解析

    • 将输入字符串转换为整数数组,明确数组长度 n(二叉树的节点总数 - 1)。
  3. 定位最小叶子节点

    • 遍历数组(从后往前,减少无效遍历),筛选出所有叶子节点;
    • 对比所有叶子节点的值,找到最小值及其索引。
  4. 回溯路径

    • 从最小叶子节点索引开始,按父节点公式依次向上找根节点;
    • 按 "根→叶子" 的顺序存储路径(用 addFirst 实现)。
  5. 结果输出

    • 将路径数组按空格拼接,返回最终字符串。

五、代码实现

java 复制代码
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Scanner;
import java.util.StringJoiner;

public class Main {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

    Integer[] arr =
        Arrays.stream(sc.nextLine().split(" ")).map(Integer::parseInt).toArray(Integer[]::new);

    System.out.println(getResult(arr));
  }

  public static String getResult(Integer[] arr) {
    int n = arr.length - 1;

    // 最小叶子节点的值
    int min = Integer.MAX_VALUE;
    // 最小叶子节点的索引
    int minIdx = -1;

    // 求解最小叶子节点的值和索引
    for (int i = n; i >= 1; i--) {
      if (arr[i] != -1) {
        if (i * 2 + 1 <= n && arr[i * 2 + 1] != -1) continue;
        if (i * 2 + 2 <= n && arr[i * 2 + 2] != -1) continue;
        if (min > arr[i]) {
          min = arr[i];
          minIdx = i;
        }
      }
    }

    // path用于缓存最小叶子节点到根的路径
    LinkedList<Integer> path = new LinkedList<>();
    path.addFirst(min);

    // 从最小叶子节点开始向上找父节点,直到树顶
    while (minIdx != 0) {
      int f = (minIdx - 1) / 2;
      path.addFirst(arr[f]);
      minIdx = f;
    }

    StringJoiner sj = new StringJoiner(" ");
    for (Integer val : path) sj.add(val + "");

    return sj.toString();
  }
}
相关推荐
he___H13 小时前
Spring中的设计模式
java·spring·设计模式
liuyao_xianhui13 小时前
优选算法_最小基因变化_bfs_C++
java·开发语言·数据结构·c++·算法·哈希算法·宽度优先
做一个AK梦13 小时前
计算机系统概论知识点(软件设计师)
java·开发语言
jimy113 小时前
C语言实现-----面向对象编程
c语言·数据结构
Kethy__13 小时前
计算机中级-数据库系统工程师-数据结构-树与二叉树(2)
数据结构·数据库·软考··计算机中级
黎阳之光13 小时前
数智技术如何赋能空天地一体化,领跑低空经济新赛道
大数据·人工智能·算法·安全·数字孪生
東雪木13 小时前
Java学习——一访问修饰符(public/protected/default/private)的权限控制本质
java·开发语言·学习·java面试
不爱吃糖的程序媛13 小时前
鸿蒙PC tiny-AES-c三方库适配实践
c语言·华为·harmonyos
两点王爷14 小时前
docker 创建和使用存储卷相关内容
java·docker·容器
boonya14 小时前
Embedding模型与向量维度动态切换完整方案
java·数据库·embedding·动态切换大模型