leetcode1719.重构一棵树的方案数

461 篇文章 1 订阅

题目:
给你一个数组 pairs ,其中 pairs[i] = [xi, yi] ,并且满足:

  • pairs 中没有重复元素
  • xi < yi

令 ways 为满足下面条件的有根树的方案数:

  • 树所包含的所有节点值都在 pairs 中。
  • 一个数对 [xi, yi] 出现在 pairs 中 当且仅当 xi 是 yi 的祖先或者 yi 是 xi 的祖先。
    注意:构造出来的树不一定是二叉树。

两棵树被视为不同的方案当存在至少一个节点在两棵树中有不同的父节点。

请你返回:

  • 如果 ways == 0 ,返回 0 。
  • 如果 ways == 1 ,返回 1 。
  • 如果 ways > 1 ,返回 2 。

一棵 有根树 指的是只有一个根节点的树,所有边都是从根往外的方向。

我们称从根到一个节点路径上的任意一个节点(除去节点本身)都是该节点的 祖先 。根节点没有祖先。

思路:
在这里插入图片描述
在这里插入图片描述

解答:

class Solution:
    def checkWays(self, pairs: List[List[int]]) -> int:
        #degree[x]:pairs 中包含节点 x 的数对的数目,等于len(adj[x])
        #adj[x]:节点 x 的祖先和后代的节点集合
        adj=defaultdict(set)
        for x,y in pairs:
            adj[x].add(y)
            adj[y].add(x)
        n=len(adj)
        #print(adj)
        #检测是否存在根节点,即是否存在一个点x,使得len(neighbors)==n
        flag=False
        for node,neighbors in adj.items():
            if len(neighbors)==n-1:
                flag=True
                root=node
                break
        #不存在根节点,不能构成一颗合法的树
        if not flag:
            return 0
        ans = 1
        #遍历每个节点,判断其父节点是否满足要求
        for node, neighbors in adj.items():
            if node == root:
                continue
            currDegree = len(neighbors)
            parent = -1
            parentDegree = float('inf')
            # 根据 degree 的大小找到 node 的父节点 parent
            for neighbor in neighbors:
                if currDegree <= len(adj[neighbor]) < parentDegree:
                    parent = neighbor
                    parentDegree = len(adj[neighbor])
            # 检测 neighbours 是否为 adj[parent] 的子集
            if parent == -1 or any(neighbor != parent and neighbor not in adj[parent] for neighbor in neighbors):
                return 0

            if parentDegree == currDegree:
                ans = 2
        return ans
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值