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差不多双指针思路,不过 这里涉及到一个很巧妙的代码技巧。
可以先自己做做看,然后看我的视频讲解。
视频讲解:不仅双指针,还有代码技巧可以惊艳到你! | 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. 二叉树的最近公共祖先
本题其实是比较难的,可以先看我的视频讲解
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;
}
};