列表

详情


LCP 26. 导航装置

小扣参加的秋日市集景区共有 $N$ 个景点,景点编号为 $1$~$N$。景点内设有 $N-1$ 条双向道路,使所有景点形成了一个二叉树结构,根结点记为 root,景点编号即为节点值。

由于秋日市集景区的结构特殊,游客很容易迷路,主办方决定在景区的若干个景点设置导航装置,按照所在景点编号升序排列后定义装置编号为 1 ~ M。导航装置向游客发送数据,数据内容为列表 [游客与装置 1 的相对距离,游客与装置 2 的相对距离,...,游客与装置 M 的相对距离]。由于游客根据导航装置发送的信息来确认位置,因此主办方需保证游客在每个景点接收的数据信息皆不相同。请返回主办方最少需要设置多少个导航装置。

示例 1:

输入:root = [1,2,null,3,4]

输出:2

解释:在景点 1、3 或景点 1、4 或景点 3、4 设置导航装置。

image.png{:height="250px"}

示例 2:

输入:root = [1,2,3,4]

输出:1

解释:在景点 3、4 设置导航装置皆可。

image.png{:height="200px"}

提示:

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ class Solution { public: int navigation(TreeNode* root) { } };

golang 解法, 执行用时: 264 ms, 内存消耗: 16.7 MB, 提交时间: 2023-10-25 23:24:22

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
 var res int
func navigation(root *TreeNode) int {
    /*
    每个三叉点(该节点既有不为空的左右子树,又有父亲节点)的三条支路中,至少两条支路上有导航装置(
    */
    res=0
    if root==nil{
        return 0
    }
    left:=dfs(root.Left)
    right:=dfs(root.Right)
        //下面这行代码是多种状态综合处理的表现形式,具体如下:
        //左右孩子状态集(左右交换就不写了):
        //[0,0]:左右都没放导航(包含子树为空的情况),那么要必须放一个导航,即res+1,而且总共放一个导航;
        //[0,1]:一个孩子没放导航,再和根节点放一起,视为最近的三叉点的一条支路。由于另一个孩子状态为1,表示该三叉点有两条支路未放导航,所以还要再增加一个导航,那么res+1;
        //[0,2]:一个孩子没放导航,再和根节点放一起,视为最近的三叉点的一条支路。另一个孩子状态为2,表示该三叉点有两条支路已放导航,所以不用再增加导航,返回res即可;
        //[1,1]:其中一个孩子和根节点放一起,视为一条支路,那么就表示该合并后的支路上有导航(只要有就可以了),所以该三叉点的两条支路有导航,返回res即可;
        //[1,2]:前面同上,该三叉点的三条支路都有导航,返回res即可;
        //[2,2]:直接同上。
        //综合上面分类情况,左右返回的状态值相加left+right>=2时,返回res即可,其他情况都要再加一个导航。
        if left+right>=2{
            return res
        }
        return res+1
}
// 0 代表该点及孩子节点都不会放导航装置
// 1 代表左右孩子都没有导航装置时,必须选一个孩子支路放一个导航装置,另一个暂时不放,以1状态标记交上面节点去处理
// 2 表示左右孩子支路都有导航装置,该节点的父节点支路可以放也可以不放导航装置
func dfs(root *TreeNode)int{
    if root==nil{
        return 0
    }
    left:=dfs(root.Left)
    right:=dfs(root.Right)
    //这里只要左右不为空,即为三叉点
    if root.Left!=nil&&root.Right!=nil{
         //左右子树都没放导航,那么必须选一条支路放一个导航,另一条支路暂时不放,返回状态1
         if left==0&&right==0{
             res+=1
             return 1
         }
         //一条支路有导航,另一条支路没有导航,继续暂时不放,返回状态1,要不要加交给上面节点来判断处理;
         if left==0||right==0{
             return 1
         }
         //左右孩子支路都有导航,那么就返回状态2
         return 2
    }else if root.Left==nil{
        //左孩子为空,该节点状态等于右孩子
        return right
    }else if root.Right==nil{
        //like
        return left
    }
    return 0
}

golang 解法, 执行用时: 252 ms, 内存消耗: 12.8 MB, 提交时间: 2023-10-25 23:24:07

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
var res = 0
var s = 1

func dfs(root *TreeNode) bool {
	if root == nil {
		return false
	}
	l := dfs(root.Left)
	r := dfs(root.Right)
	if root.Left != nil && root.Right != nil {
		if !l && !r {
			res++
		}
		if !(l && r) {
			s = 1
		} else {
			s = 0
		}
		return true
	}
	return l || r
}
func navigation(root *TreeNode) int {
	res = 0
	s = 1
	l := dfs(root.Left)
	r := dfs(root.Right)
	if l && r {
		return res
	}
	return res + s
}

python3 解法, 执行用时: 984 ms, 内存消耗: 81.5 MB, 提交时间: 2023-10-25 23:23:43

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def navigation(self, root: TreeNode) -> int:
        def get(node):
            if node is None:
                return [0, 1, 1, 1]
            elif hasattr(node, 'result'):
                return node.result
            if not node.left and not node.right:
                result = [0, 1, 1, 1]
            elif not node.left or not node.right:
                result = get(node.left) if node.left else get(node.right)
                result[1] = min(result[0] + 1, result[3])
            else:
                result = [0xffffffff] * 4
                l, r = get(node.left), get(node.right)
                result[3] = min(l[1] + r[3], l[3] + r[1], l[2] + r[2])
                result[2] = min(result[3], l[0] + r[2], l[2] + r[0])
                result[1] = min(result[3], l[0] + r[3], l[3] + r[0])
                result[0] = min(result[1], result[2], l[0] + r[2], l[2] + r[0])
            setattr(node, 'result', result)
            return node.result

        return get(root)[1]

java 解法, 执行用时: 9 ms, 内存消耗: 56.2 MB, 提交时间: 2023-10-25 23:23:05

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    int res = 0;

    public int navigation(TreeNode root) {
        if (root == null) return 0;
        //根节点单独处理
        int left = dfs(root.left);
        int right = dfs(root.right);
        //下面这行代码是多种状态综合处理的表现形式,具体如下:
        //左右孩子状态集(左右交换就不写了):
        //[0,0]:左右都没放导航(包含子树为空的情况),那么要必须放一个导航,即res+1,而且总共放一个导航;
        //[0,1]:一个孩子没放导航,再和根节点放一起,视为最近的三叉点的一条支路。由于另一个孩子状态为1,表示该三叉点有两条支路未放导航,所以还要再增加一个导航,那么res+1;
        //[0,2]:一个孩子没放导航,再和根节点放一起,视为最近的三叉点的一条支路。另一个孩子状态为2,表示该三叉点有两条支路已放导航,所以不用再增加导航,返回res即可;
        //[1,1]:其中一个孩子和根节点放一起,视为一条支路,那么就表示该合并后的支路上有导航(只要有就可以了),所以该三叉点的两条支路有导航,返回res即可;
        //[1,2]:前面同上,该三叉点的三条支路都有导航,返回res即可;
        //[2,2]:直接同上。
        //综合上面分类情况,左右返回的状态值相加left+right>=2时,返回res即可,其他情况都要再加一个导航。
        if(left + right >= 2){
            return res;
        }
        return res + 1;
    }

    public int dfs(TreeNode root) {
        //为空时,表示没放导航
        if (root == null) return 0;
        int left = dfs(root.left);
        int right = dfs(root.right);
        //由于上面根节点单独处理,所以这里只要左右不为空,即为三叉点
        if (root.left != null && root.right != null) {
            //左右子树都没放导航,那么必须选一条支路放一个导航,另一条支路暂时不放,返回状态1;
            if(left == 0 && right == 0){
                res += 1;
                return 1;
            }
            //一条支路有导航,另一条支路没有导航,继续暂时不放,返回状态1,要不要加交给上面节点来判断处理;
            //这里多说一句,由于该三叉节点一条有导航另一条没导航,那么对于之前已经遍历的下面的三叉点来说,相当于它的父节点支路有导航了,所以当时处理它时,是否有一条支路未放导航就无所谓了;
            if(left == 0 || right == 0){
                return 1;
            }
            //左右孩子支路都有导航,那么就返回状态2
            return 2;
        }else if(root.left == null){//左孩子为空,该节点状态等于右孩子,或者说把最近的三叉点状态往上传递
            return right;
        }else if(root.right == null){//同上理
            return left;
        }
        //由于编译器的原因,加这么一句,这里是你永远到不了的地方
        return 0;
    }
}

python3 解法, 执行用时: 676 ms, 内存消耗: 80.4 MB, 提交时间: 2023-10-25 23:22:37

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def navigation(self, root: TreeNode) -> int:
        self.res = 0
        self.s = 1 # 根是否要加一个
        def dfs(node):
            if not node:
                return False
            l = dfs(node.left)
            r = dfs(node.right)
            # 这是一个三叉
            if node.left and node.right:
                # 左右如果目前都没有,那必须左右至少有一个
                if (not l) and (not r):
                    self.res += 1
                
                # 左右不是俩都有,那无论如何根得加一个
                if not (l and r):
                    self.s = 1
                else:
                    self.s = 0
                
                return True
                
            return l or r

        l = dfs(root.left)
        r = dfs(root.right)

        # 如果左右都有,根就不需要了
        if l and r:
            return self.res
        # 如果左右只有一个,那么我们就拿那棵没有的树当父树然后 + s(对父树有需求+1,没需求不加)
        else:
            return self.res + self.s

cpp 解法, 执行用时: 436 ms, 内存消耗: 283.8 MB, 提交时间: 2023-10-25 23:22:19

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int res = 0, s = 1;
    int dfs(TreeNode* root) {
        if(!root) {
            return 0;
        }
        int l = dfs(root->left), r = dfs(root->right);
        if(root->left && root->right) {
            res += !l && !r;
            s = !(l && r);
            return 1;
        }
        return l || r;
    }
    int navigation(TreeNode* root) {
        int l = dfs(root->left), r = dfs(root->right);
        return res + ((l && r)? 0 : s);
    }
};

上一题