二叉树供暖问题 | 豆包MarsCode AI刷题

47 阅读3分钟

思路: 我们可以建立一个二叉树,然后自底向上遍历节点的情况。然后我们只需根据节点处理两种情况:对于叶子节点它的父节点一定是供暖节点,其他非叶子节点就根据它的子节点情况讨论。这些情况具体是:该节点是供暖节点就可以直接返回,该节点的子节点有一个是供暖节点该节点就是被供暖节点,该节点是被供暖节点而且子节点有一个没被供暖那他就要成为供暖节点。

按照这个思路,我们对叶子节点处理好后只需对非叶子节点讨论,而且对叶子节点讨论时只需关注该节点的子节点就行。

public class Main {
    public static class Node{
        boolean energy,get;
        Node left,right,father;
        Node(){
            energy=false;
            get=false;
            left=null;
            right=null;
            father=null;
        }
        Node(Node f){
            energy=false;
            get=false;
            left=null;
            right=null;
            father=f;
        
        }
    }

    //层次建树
    public static Node cengbuild(int[] nodes){
        int length=nodes.length;
        //层次建树,用队列
        Queue<Node> que=new LinkedList<>();
        Node p=new Node(null);
        Node root=p;
        que.add(p);
        int i=1;
        while(!que.isEmpty()){
            p=que.poll();
            if(nodes[i++]!=0){
                p.left=new Node(p);
                que.add(p.left);
            }
            if(i==length){
                break;
            }
            if(nodes[i++]!=0){
                p.right=new Node(p);
                que.add(p.right);
            }
            if(i==length){
                break;
            }
        }
        return root;
    }


    //全局变量,用来统计的
    static int count=0;
    //从根节点开始处理供暖
    public static void solve(Node n){
        if(n==null||n.energy){
            return;
        }
        solve(n.left);
        solve(n.right);
        //如果这个节点是叶子节点,那么它的父节点必定要火炉!
        if(n.left==null&&n.right==null){
            if(!n.father.energy){
                n.father.energy = true;
                count++;
            }
            return;
        }
        //供暖节点,直接返回
        if(n.energy){
            return ;
        }
       //对于其他的条件,就单独一个非叶子节点来说,可以将节点分为供暖、被供暖,没供暖三种状态
        //对于供暖节点,一开始已经return了
        //接下来讨论被供暖节点(子节点有一个是供暖的!)和没供暖的节点(get是false的节点!),在出现没供暖子节点的情况下要变成供暖节点
        //如果子节点有一个是供暖节点,那么他就是被供暖的节点
        if(n.left!=null&&n.left.energy||n.right!=null&&n.right.energy){
            n.get=true;
        }


        //只要出现一个没被供暖,他就要变成供暖
        if(n.left!=null&&!n.left.energy&&!n.left.get){
            n.energy=true;
            count++;
            return;
        }
        if(n.right!=null&&!n.right.energy&&!n.right.get){
            n.energy=true;
            count++;
            return;
        }
       

    }

    public static int solution(int[] nodes) {
        //先清除记录!
        count=0;
        int length=nodes.length;
        if(length<=3){
            return 1;
        }
        //测试
        Node cengbuild = cengbuild(nodes);
        solve(cengbuild);
     
        return count;
    }

   
}

一、解题思路

  1. 建立二叉树:首先根据输入的数组建立二叉树,使用队列实现层序建树。

  2. 遍历二叉树:从根节点开始,自底向上遍历二叉树,判断每个节点是否需要放置暖炉。

  3. 状态判断:

    • 叶子节点:叶子节点的父节点必须放置暖炉。

    • 非叶子节点:根据子节点的情况判断当前节点是否需要放置暖炉。

      • 如果子节点中有供暖节点,则当前节点为被供暖节点。
      • 如果子节点中有未被供暖的节点,则当前节点需要放置暖炉。
  4. 统计暖炉数量:使用全局变量count记录需要放置的暖炉数量。

二、代码实现

  1. 定义节点类Node,包含能量状态、供暖状态、左右子节点及父节点。
  2. 层序建树函数cengbuild:根据输入数组建立二叉树。
  3. 解决供暖问题函数solve:从根节点开始,递归遍历二叉树,判断每个节点是否需要放置暖炉。
  4. 主函数solution:调用cengbuild和solve函数,返回需要放置的暖炉数量。