【每日一题】将一维数组转换成树状结构

245 阅读2分钟

【题目】将一维数组转换成树状结构

【描述】

假设有一个包含多个对象的数组 arr,每个对象都有两个属性:idparentId。其中,id 表示该对象的唯一标识符,parentId 表示该对象所属的父级对象的 id。如果该对象没有父级,则 parentIdnull

例如,对于下面的数组:

const arr = [
  { id: 1, parentId: null },
  { id: 2, parentId: 1 },
  { id: 3, parentId: 1 },
  { id: 4, parentId: 2 },
  { id: 5, parentId: 2 },
  { id: 6, parentId: 3 },
  { id: 7, parentId: 3 },
];

可以看出,该数组描述了一个树形结构,其中 id 是节点的标识符,parentId 是该节点在树中的父节点的标识符。例如,节点 1 没有父节点,因此其 parentIdnull;节点 4 和节点 5 的父节点都是节点 2。

请编写一个函数 buildTree(arr),将以上数组转换为一个树形结构,并返回树的根节点(即 parentIdnull 的节点)。

要求:

  • 返回的树形结构应该是一个对象,其包含 id 和 children 两个属性,id 表示节点的标识符,children 表示该节点的子节点数组。
  • 如果某个节点没有子节点,则其 children 属性应该为空数组。
  • 如果输入的数组中不存在根节点(即 parentId 为 null 的节点),则返回 null

例如,对于上面的数组 arr,调用 buildTree(arr) 应该返回以下对象:

{
  id: 1,
  children: [
    {
      id: 2,
      children: [
        { id: 4, children: [] },
        { id: 5, children: [] }
      ]
    },
    {
      id: 3,
      children: [
        { id: 6, children: [] },
        { id: 7, children: [] }
      ]
    }
  ]
}

请实现函数 buildTree(arr)

0caa9fe39ff74023a0a79887d008162a_3.png

【答案】

function buildTree(arr) {
  const nodeMap = {};
  let root;

  // 构建节点映射表
  arr.forEach(obj => {
    const { id, parentId } = obj;
    if (!nodeMap[id]) {
      nodeMap[id] = { id, children: [] };
    }
    if (parentId === null) {
      root = nodeMap[id]; // 将根节点保存为 root
    } else {
      if (!nodeMap[parentId]) {
        nodeMap[parentId] = { id: parentId, children: [] };
      }
      nodeMap[parentId].children.push(nodeMap[id]);
    }
  });

  return root || null; // 返回根节点,如果没有根节点则返回 null
}

// 测试样例
const arr = [
  { id: 1, parentId: null },
  { id: 2, parentId: 1 },
  { id: 3, parentId: 1 },
  { id: 4, parentId: 2 },
  { id: 5, parentId: 2 },
  { id: 6, parentId: 3 },
  { id: 7, parentId: 3 },
];

const tree = buildTree(arr);
console.log(tree);


这个解法使用一个对象 nodeMap 来构建节点的映射表,并找到根节点。在遍历原始数组时,如果某个节点的 parentIdnull,则将该节点设置为根节点 root。对于其他节点,将它们添加到对应的父节点的 children 数组中。最后返回根节点。这个解法可以正确地构建出树形结构,并输出根节点。如果没有根节点,则返回 null

扫码_搜索联合传播样式-白色版.png