六月集训(第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;
    }
};
posted @ 2022-06-18 14:15  番茄元  阅读(25)  评论(0)    收藏  举报