Day21 二叉树 530 501 236

75 阅读3分钟

530. 二叉搜索树的最小绝对差

心得

  • 看到题目想的递增排序求差值,后来想能否不同额外空间,分析了下可能出现最值的位置,想多了
  • 其实应该首先按照数组逻辑,然后将数组的操作逻辑拷贝到二叉树上,进行优化,数组

题解

  • 中序+双指针法,数组也是用前后两个进行比较,区别可能数组prev初始为首位,切到二叉树,对应加个首位判断即可,同时递增考虑有序性,不用abs
  • 求最值、差值这种相邻元素的均可以采用prev指针技巧
class Solution {
public:
    TreeNode* prev;
    int result = INT_MAX;
    void traversal(TreeNode* cur) {
        if (cur == nullptr) return;
        traversal(cur->left); // 左,其实存在回溯过程
        if (prev != nullptr) {
            result = min(result, cur->val - prev->val); // 中
        }
        prev = cur; // 双指针精华
        traversal(cur->right); // 右
    }
    int getMinimumDifference(TreeNode* root) {
        traversal(root);
        return result;
    }
};

501. 二叉搜索树中的众数

心得

  • 开始想的中序遍历记录结果成有序数组,然后在有序数组基础上进行求众数,但是想的是此时求众数可能会设计滑动窗口,其实想的复杂了,之前类似的有序数组解法也都是双指针来进行操作
  • 同时目标数组清理想的循环pop出去,其实该情况下直接用模板函数即可

题解

  • 用好双指针,在有序数组计数基础上,类比2个指针分别进行记录当前和最值,高于则重置,等于添加结果
  • 看似简单,实则不易,细想又理应如此,还是要多思考,明确思路,按步骤即可
class Solution {
public:
    TreeNode* prev = nullptr;
    int count = 0;
    int maxCount = 0;
    vector<int> result;
    void traversal(TreeNode* cur) {
        if (cur == nullptr) return;
        traversal(cur->left); // 左
        // 中
        if (prev == nullptr) {  // 对元素进行计数
            count = 1;
        } else if (cur->val == prev->val) {
            count++;
        } else {
            count = 1;
        }
        // 对计数结果进行比对
        if (count == maxCount) {
            result.push_back(cur->val);
        }
        if (count > maxCount) { // 之前数组作废
            maxCount = count;
            result.clear(); // 清除之前的
            result.push_back(cur->val);
        }
        prev = cur;
        // 右
        traversal(cur->right);
        return ;
    }

    vector<int> findMode(TreeNode* root) {
        traversal(root);
        return result;
    }
};

236. 二叉树的最近公共祖先

心得

  • 完全没思路,其实是题意没理解到位,找到目标,判断左右子树有无即可

题解

  • 从下往上遍历,对于二叉树不可能,只有从上往下,那么只能通过递归回溯来实现(通过后序遍历实现),先需要左右的值然后再进行处理,跟之前深度的思路一致,遇到p q不断返回即可
  • 注意第二种情况,p q其中一种为另一个的直接祖先情况,已经包含在内
  • 小细节,有return值时,不能为了好看4个if,必须要返回,可以用最后一个else来确定返回值
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (root == nullptr) return nullptr;
        if (root == p || root == q) return root;
        TreeNode* left = lowestCommonAncestor(root->left, p, q); // 找到第一个符合的就返回
        TreeNode* right = lowestCommonAncestor(root->right, p, q);
        if (left != nullptr && right != nullptr) return root;
        // 其中一个为另一个的祖先情况包含在这种和下面情况
        else if (left != nullptr && right == nullptr) return left; 
        else if (left == nullptr && right != nullptr) return right;
        else return nullptr;
    }
};
// 简化版
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (root == p || root == q || root == nullptr) return root;
        TreeNode* left = lowestCommonAncestor(root->left, p, q);
        TreeNode* right = lowestCommonAncestor(root->right, p, q);
        if (left != nullptr && right != nullptr) return root;
        // 其中一个为另一个的祖先情况包含在这种和下面情况
        else if (left != nullptr && right == nullptr) return left; 
        return right;
    }
};