算法D20 | 二叉树7 | 530.二叉搜索树的最小绝对差 501.二叉搜索树中的众数 236. 二叉树的最近公共祖先

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

需要领悟一下二叉树遍历上双指针操作,优先掌握递归 题目链接/文章讲解:https://programmercarl.com/0530.%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91%E7%9A%84%E6%9C%80%E5%B0%8F%E7%BB%9D%E5%AF%B9%E5%B7%AE.html

视频讲解:二叉搜索树中,需要掌握如何双指针遍历!| LeetCode:530.二叉搜索树的最小绝对差_哔哩哔哩_bilibili

Python递归- 中序遍历:

二叉搜索树中序遍历的结果是有序数组。

这里补充一下python引用传递和值传递的问题,当arr作为参数传入的时候,由于arr是python的基本类型,所以是引用传递;如果在C++语法中仅传入参数 值传递,则不会修改。

Python 中的函数传参是通过对象引用进行的,如果传的是一个不可变对象(在其他语言中可能指基本类型),函数中对这个参数的更改是不会影响到函数外的,这个传递也就是值传递。如果传的是 list,字典,集合作为参数,传递的参数可以看做是引用传递,对其进行的更改就能影响到函数外

class Solution:
    def traversal(self, node, arr):
        if not node: return
        self.traversal(node.left, arr)
        arr.append(node.val)
        self.traversal(node.right, arr)
        return 

    def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
        if not root: return
        arr = []
        self.traversal(root, arr)
        min_diff = float('inf')
        for i in range(1, len(arr)):
            _diff = arr[i] - arr[i-1]
            min_diff = min(min_diff, _diff)
        return min_diff

Python递归- 中序遍历- 双指针:

用双指针记录相邻节点,这样不用额外储存整个树到arr。内存占用减半。

class Solution:
    def __init__(self):
        self.result = float('inf')
        self.pre = None

    def traversal(self, cur):
        if not cur: return
        # 左
        self.traversal(cur.left)
        # 中
        if self.pre:
            self.result = min(self.result, cur.val - self.pre.val)
        self.pre = cur
        # 右
        self.traversal(cur.right)
        return 

    def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
        self.traversal(root)
        return self.result

C++ 递归- 中序遍历- 双指针:

class Solution {
public:
    int result = INT_MAX;
    TreeNode* pre;
    void traversal(TreeNode* cur) {
        if (cur==NULL) return;
        traversal(cur->left);
        if (pre!=NULL) {
            result = min(result, cur->val - pre->val);
        } 
        pre = cur;
        traversal(cur->right);
    }
    int getMinimumDifference(TreeNode* root) {
        traversal(root);
        return result;
    }
};

501.二叉搜索树中的众数 

和 530差不多双指针思路,不过 这里涉及到一个很巧妙的代码技巧。

可以先自己做做看,然后看我的视频讲解。

https://programmercarl.com/0501.%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91%E4%B8%AD%E7%9A%84%E4%BC%97%E6%95%B0.html

视频讲解:不仅双指针,还有代码技巧可以惊艳到你! | LeetCode:501.二叉搜索树中的众数_哔哩哔哩_bilibili

Python递归 - 中序遍历:

这里有一个细节需要想清楚,traversal-中部分,先遍历,再记录结果,这样区分会比较清晰,不混乱。

class Solution:
    def __init__(self):
        self.result = []
        self.result_freq = 0
        self.pre = None
        self.cur_freq = 0
    
    def traversal(self, cur):
        if not cur: return
        # 左
        self.traversal(cur.left)
        # 中
        if not self.pre:
            self.cur_freq = 1 
        elif cur.val == self.pre.val:
            self.cur_freq += 1
        else:
            self.cur_freq = 1 
        self.pre = cur
        # 记录结果
        if self.cur_freq == self.result_freq:
            self.result.append(cur.val) # append结果
        elif self.cur_freq > self.result_freq:
            self.result = [cur.val]     # reset结果
            self.result_freq = self.cur_freq # 更新result里的freq
        # 右          
        self.traversal(cur.right)
        return

    def findMode(self, root: Optional[TreeNode]) -> List[int]:
        if not root: return
        self.traversal(root)
        return self.result

C++版本:

class Solution {
public:
    vector<int> result;
    int maxCnt;
    TreeNode* pre;
    int cnt;

    void traversal(TreeNode* cur) {
        if (cur==NULL) return;
        traversal(cur->left);
        if (pre==NULL) {
            cnt = 1;
        } else if (pre->val == cur->val) {
            cnt++;
        } else {
            cnt = 1;
        }
        pre = cur;
        if (cnt == maxCnt) {
            result.push_back(cur->val);
        } else if (cnt > maxCnt) {
            result = {cur->val};
            maxCnt = cnt;
        }
        traversal(cur->right);
    }

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

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

本题其实是比较难的,可以先看我的视频讲解 

https://programmercarl.com/0236.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E6%9C%80%E8%BF%91%E5%85%AC%E5%85%B1%E7%A5%96%E5%85%88.html

视频讲解:自底向上查找,有点难度! | LeetCode:236. 二叉树的最近公共祖先_哔哩哔哩_bilibili

Python递归 - 后序遍历(回溯):

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        if (not root or root==p or root==q): return root

        left = self.lowestCommonAncestor(root.left, p, q)
        right = self.lowestCommonAncestor(root.right, p, q)
        if left and right:
            return root
        if not left and right:
            return right
        elif left and not right:
            return left
        else:
            return

也可以精简成:

    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        if (not root or root==p or root==q): return root
        left = self.lowestCommonAncestor(root.left, p, q)
        right = self.lowestCommonAncestor(root.right, p, q)
        if left and right:
            return root
        if not left :
            return right
        return left

C++版本:

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (root==NULL || root==p || root==q) return root;
        TreeNode* left = lowestCommonAncestor(root->left, p, q);
        TreeNode* right = lowestCommonAncestor(root->right, p, q);
        if (left!=NULL && right!=NULL) return root;
        if (left==NULL) return right;
        return left;  
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值