六月集训(第18天)—树
树
1. 1361. 验证二叉树
思路:
考虑是否能生成二叉树,从入度的角度看
(1) 不存在indeg == 0的点,就没有树根,不是二叉树
(2) 存在indeg >= 2 的点,说明该结点有两个父节点,不是二叉树
(3) 有大于等于2个的indeg == 0的结点,说明不止一棵树,是森林
如果满足上述三点,则能生成一颗二叉树,找到indeg == 0的树根,遍历二叉树,标记每个遍历到的结点。最后检查是否所有结点都被标记,是则返回ture;否则返回false。
class Solution {
bool vis[10010];
void dfs(int root, vector<int> &leftChild, vector<int> &rightChild) {
vis[root] = true;
if (leftChild[root] != -1) dfs(leftChild[root], leftChild, rightChild);
if (rightChild[root] != -1) dfs(rightChild[root], leftChild, rightChild);
}
public:
bool validateBinaryTreeNodes(int n, vector<int>& leftChild, vector<int>& rightChild) {
int indeg[n], i; // 结点i的入度为indeg[i]
int root = 0, cnt = 0; // cnt统计入度等于0的结点个数
memset(indeg, 0, sizeof(indeg));
// 通过统计结点的入度判断是否能生成二叉树
for (i = 0; i < n; ++i) {
if (leftChild[i] != -1) indeg[leftChild[i]]++;
if (rightChild[i] != -1) indeg[rightChild[i]]++;
}
for (i = 0; i < n; ++i) {
if (indeg[i] == 0) {
cnt++;
root = i;
if (cnt > 1) return false;
} else if (indeg[i] >= 2) return false;
}
if (cnt == 0) return false; // 没有根节点
// 遍历二叉树,判断是否每个结点都遍历过了
dfs(root, leftChild, rightChild);
for (i = 0; i < n; ++i) if (!vis[i]) return false;
return true;
}
};
2. 1367. 二叉树中的列表
思路:
二叉树中的每个结点都有可能作为head找到head链,所以每个root结点都可能作为递归起点,再递归遍历以该起点为根节点的二叉树,寻找目标链即可。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
bool check(ListNode *head, TreeNode *root) {
if (root == nullptr) return head == nullptr;
if (head == nullptr) return true;
if (root->val != head->val) return false;
return check(head->next, root->left) || check(head->next, root->right);
}
public:
bool isSubPath(ListNode* head, TreeNode* root) { // 以树上每一个结点作为起点向下寻找head链
if (check(head, root)) return true; // 当前结点往下可以找到
if (root == nullptr) return false; // 还没找到head链,树已经遍历完了,即每个结点都不满足
return isSubPath(head, root->left) || isSubPath(head, root->right);
}
};
3. 1457. 二叉树中的伪回文路径
思路:
伪回文路径,即二叉树从根节点到某个叶结点的路径上所有值可以构成回文串,统计每个值出现的次数,最多有一个值出现了奇数次才能满足题意。
(1) 先序遍历二叉树,统计从根结点到达某个叶节点路径上的值出现的次数
(2) 在叶结点处判断是否出现奇数次的值只有0个或1个,是则答案+1。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
int cnt[10];
int ans;
void dfs(TreeNode *root) {
if (root == nullptr) return ; // 结点为空则返回
cnt[root->val]++; // 记录当前结点值出现一次
if (root->left == nullptr && root->right == nullptr) { // 到叶节点更新答案
int odd_cnt = 0;
for (int i = 0; i < 10; ++i) {
if (cnt[i] & 1) odd_cnt++;
}
if (odd_cnt == 0 || odd_cnt == 1) ans++;
}
dfs(root->left);
dfs(root->right);
cnt[root->val]--; // 回溯的时候删除当前结点值
}
public:
int pseudoPalindromicPaths (TreeNode* root) {
ans = 0;
dfs(root);
return ans;
}
};
4. 1373. 二叉搜索子树的最大键值和
思路:
利用二叉搜索树的性质,根节点大于左子树的最大值,小于右子树的最小值,判定每棵子树是否为二叉搜索树,如果满足则利用其子树结点的数值和更新答案。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
int ans = 0;
void dfs(TreeNode *root, int *maxv, int *minv, int *sum, int *isBST) {
if (root == nullptr) {
*maxv = -INT_MAX;
*minv = INT_MAX;
*sum = 0;
*isBST = 1;
return ;
}
int lmax, lmin, lsum, lisBST;
int rmax, rmin, rsum, risBST;
dfs(root->left, &lmax, &lmin, &lsum, &lisBST);
dfs(root->right, &rmax, &rmin, &rsum, &risBST);
*sum = root->val;
if (lmax < root->val && root->val < rmin && lisBST && risBST) { // 以root为根节点的子树是二叉搜索树
*sum = root->val + lsum + rsum;
*isBST = 1;
} else {
*isBST = 0;
*sum = 0;
}
*maxv = max(lmax, rmax);
*maxv = max(*maxv, root->val);
*minv = min(lmin, rmin);
*minv = min(*minv, root->val);
ans = max(ans, *sum);
}
public:
int maxSumBST(TreeNode* root) {
int maxv, minv, sum, isBST;
dfs(root, &maxv, &minv, &sum, &isBST);
return ans;
}
};
东方欲晓,莫道君行早。

浙公网安备 33010602011771号