惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

IT之家
IT之家
腾讯CDC
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
K
Kaspersky official blog
V
Visual Studio Blog
博客园 - 聂微东
Recent Commits to openclaw:main
Recent Commits to openclaw:main
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
云风的 BLOG
云风的 BLOG
T
Tailwind CSS Blog
C
Check Point Blog
H
Heimdal Security Blog
The GitHub Blog
The GitHub Blog
Google Online Security Blog
Google Online Security Blog
P
Proofpoint News Feed
AI
AI
The Register - Security
The Register - Security
SecWiki News
SecWiki News
Help Net Security
Help Net Security
T
Troy Hunt's Blog
V
V2EX
T
Tenable Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Forbes - Security
Forbes - Security
P
Privacy International News Feed
Microsoft Azure Blog
Microsoft Azure Blog
A
About on SuperTechFans
Recorded Future
Recorded Future
C
Cybersecurity and Infrastructure Security Agency CISA
博客园 - 司徒正美
博客园 - 叶小钗
Y
Y Combinator Blog
人人都是产品经理
人人都是产品经理
S
Security @ Cisco Blogs
罗磊的独立博客
Apple Machine Learning Research
Apple Machine Learning Research
L
LINUX DO - 最新话题
V2EX - 技术
V2EX - 技术
The Cloudflare Blog
Jina AI
Jina AI
T
The Exploit Database - CXSecurity.com
L
Lohrmann on Cybersecurity
Webroot Blog
Webroot Blog
美团技术团队
N
News and Events Feed by Topic
小众软件
小众软件
Google DeepMind News
Google DeepMind News
G
GRAHAM CLULEY
阮一峰的网络日志
阮一峰的网络日志
B
Blog

博客园 - Grandyang

[LeetCode] 1372. Longest ZigZag Path in a Binary Tree 二叉树中的最长交错路径 [LeetCode] 1371. Find the Longest Substring Containing Vowels in Even Counts 每个元音包含偶数次的最长子字符串 [LeetCode] 1370. Increasing Decreasing String 上升下降字符串 [LeetCode] 1368. Minimum Cost to Make at Least One Valid Path in a Grid 使网格图至少有一条有效路径的最小代价 [LeetCode] 1367. Linked List in Binary Tree 二叉树中的链表 [LeetCode] 1366. Rank Teams by Votes 通过投票对团队排名 [LeetCode] 1365. How Many Numbers Are Smaller Than the Current Number 有多少小于当前数字的数字 [LeetCode] 1363. Largest Multiple of Three 形成三的最大倍数 [LeetCode] 1362. Closest Divisors 最接近的因数 [LeetCode] 1360. Number of Days Between Two Dates 日期之间隔几天 [LeetCode] 1359. Count All Valid Pickup and Delivery Options 有效的快递序列数目 [LeetCode] 1358. Number of Substrings Containing All Three Characters 包含所有三种字符的子字符串数目 [LeetCode] 1357. Apply Discount Every n Orders 每隔n个顾客打折 [LeetCode] 1356. Sort Integers by The Number of 1 Bits 根据数字二进制下1 的数目排序 [LeetCode] 1354. Construct Target Array With Multiple Sums 多次求和构造目标数组 [LeetCode] 1353. Maximum Number of Events That Can Be Attended 最多可以参加的会议数目 [LeetCode] 1352. Product of the Last K Numbers 最后 K 个数的乘积 [LeetCode] 1351. Count Negative Numbers in a Sorted Matrix 统计有序矩阵中的负数 [LeetCode] 1349. Maximum Students Taking Exam 参加考试的最大学生数
[LeetCode] 1361. Validate Binary Tree Nodes 验证二叉树
Grandyang · 2023-11-20 · via 博客园 - Grandyang

You have n binary tree nodes numbered from 0 to n - 1 where node i has two children leftChild[i] and rightChild[i], return true if and only if all the given nodes form exactly one valid binary tree.

If node i has no left child then leftChild[i] will equal -1, similarly for the right child.

Note that the nodes have no values and that we only use the node numbers in this problem.

Example 1:

Input: n = 4, leftChild = [1,-1,3,-1], rightChild = [2,-1,-1,-1]
Output: true

Example 2:

Input: n = 4, leftChild = [1,-1,3,-1], rightChild = [2,3,-1,-1]
Output: false

Example 3:

Input: n = 2, leftChild = [1,0], rightChild = [-1,-1]
Output: false

Constraints:

  • n == leftChild.length == rightChild.length
  • 1 <= n <= 104
  • -1 <= leftChild[i], rightChild[i] <= n - 1

这道题说是给了两个数组 leftChild 和 rightChild,其中 leftChild[i] 表示结点i的左子结点,rightChild[i] 表示结点i的右子结点,若值为 -1,表示没有左子结点或着右子结点,问给定的数组是否可以组成一个有效的二叉树。对于二叉树想必大家都不陌生,来看一下题目中给的例子,例子1是一棵有效的二叉树,例子2中由于结点3有两个父结点,所以不是有效的二叉树,例子3中两个结点互为父结点了,这也不是有效的二叉树。二叉树是一种特殊的有向图,一棵有效的二叉树至少要具备这个几个特点,首先是只有一个根结点,即所有结点必须是连成一个整体的,其次是每个结点最多有两个子结点,然后每个结点最多只有一个父结点,最后就是不能出现环。

有向图有个入度 In Degree 的概念,就是某个结点被其他结点连通的个数,对于有效二叉树来说,除了根结点之外的每个结点的入度必须是1,即每个结点最多只有一个父结点,根结点的入度是0,其没有父结点。那这里就可以通过计算每个结点的入度,来快速去除一些无效的二叉树,这里用个长度为n的入度数组 inDegree,然后遍历两个数组,若左子结点不为 -1,则将其入度值自增1,此时判断一下,若入度值大于1了,说明是无效的二叉树,返回 false,对右子结点进行相同的处理。

仅判断结点的入度值是不够的,比如例子3中,每个结点的入度都是1,但不是有效二叉树,因为其没有根结点,所以接下来需要找出根结点,而且只能有一个根结点,就是说只能有一个结点的入度是0,若找到了多个,则返回 false。找到了根结点后也还不能说就是有效的二叉函数了,还得保证所有的结点都是相连的,这个通过从根结点开始遍历二叉树,统计遍历到的结点个数,若成功遍历了n个结点,才能说是有效的二叉树。遍历的方法可以用 BFS 或者 DFS,这里先用 BFS,使用队列 queue 来辅助运算,先把根结点 root 放进去,然后进行 while 循环,每次从 queue 中取出一个结点,计数器 cnt 自增1,然后看其左右子结点,若存在就加入到队列中继续循环,最后判断 cnt 是否等于n即可,参见代码如下:

解法一:

class Solution {
public:
    bool validateBinaryTreeNodes(int n, vector<int>& leftChild, vector<int>& rightChild) {
        int root = -1, cnt = 0;
        vector<int> inDegree(n);
        for (int i = 0; i < n; ++i) {
            int left = leftChild[i], right = rightChild[i];
            if (left != -1 && ++inDegree[left] > 1) return false;
            if (right != -1 && ++inDegree[right] > 1) return false;
        }
        for (int i = 0; i < n; ++i) {
            if (inDegree[i] != 0) continue;
            if (root != -1) return false;
            root = i;
        }
        if (root == -1) return false;
        queue<int> q{{root}};
        while (!q.empty()) {
            auto t = q.front(); q.pop();
            ++cnt;
            if (leftChild[t] != -1) q.push(leftChild[t]);
            if (rightChild[t] != -1) q.push(rightChild[t]);
        }
        return cnt == n;
    }
};

下面解法是用 DFS 来遍历二叉树,写起来更加简洁一些,在递归函数中首先判断若当前结点 node 为 -1,说明不存在,则返回0,否则分别对其左右子结点调用递归函数,将返回值加起来,再加上1,就是以当前结点 node 为根结点的二叉树的结点个数了,参见代码如下:

解法二:

class Solution {
public:
    bool validateBinaryTreeNodes(int n, vector<int>& leftChild, vector<int>& rightChild) {
        int root = -1, cnt = 0;
        vector<int> inDegree(n);
        for (int i = 0; i < n; ++i) {
            int left = leftChild[i], right = rightChild[i];
            if (left != -1 && ++inDegree[left] > 1) return false;
            if (right != -1 && ++inDegree[right] > 1) return false;
        }
        for (int i = 0; i < n; ++i) {
            if (inDegree[i] != 0) continue;
            if (root != -1) return false;
            root = i;
        }
        if (root == -1) return false;
        return countNodes(leftChild, rightChild, root) == n;
    }
    int countNodes(vector<int>& leftChild, vector<int>& rightChild, int node) {
        if (node == -1) return 0;
        return 1 + countNodes(leftChild, rightChild, leftChild[node]) + countNodes(leftChild, rightChild, rightChild[node]);
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/1361

参考资料:

https://leetcode.com/problems/validate-binary-tree-nodes/

https://leetcode.com/problems/validate-binary-tree-nodes/solutions/517557/c-find-root-dfs/

LeetCode All in One 题目讲解汇总(持续更新中...)