碎碎念:
参考:代码随想录
530.二叉搜索树的最小绝对差
题目链接
思想
直白想法:
先中序遍历,得到有序的序列,然后再求最小绝对差。
这样的操作多开辟了一个数组,其实可以优化,使用双指针来求最小绝对差。
双指针优化:
定义一个pre指向当前遍历之前的节点。
定义一个全局变量result,出事为maxint,记录相邻节点差值的最小值。
递归三部曲:
- 参数和返回值
- 终止条件:cur遍历到NULL。
- 单层递归:左:向左递归。
中:当pre!=NULL,计算pre和cur指向节点值的差值,更新最小的result。更新pre和cur。
右:向右递归。
题解
class Solution {
public:
int result = INT_MAX;
TreeNode* pre = NULL;
void traversal(TreeNode* cur) {
if (cur == NULL) return;
traversal(cur->left); // 输入的是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;
}
};
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)
def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
self.traversal(root)
return self.result
反思
注意本题也是暗含回溯的。
501.二叉搜索树中的众数
题目链接
思想
普通二叉树的解法: 要把符合题意的解都放到数组中。用map来统计元素出现的频率。然后map转为vector进行排序。再求众数。
如何利用二叉搜索树的特性来求众数。
遇到二叉搜索树时一定是中序遍历。因为中序遍历得到的序列是有序的。
问题:需要遍历两遍二叉树?第一遍得出出现的最大的频率,第二遍再得出出现频率等于最大频率的数(也就是众数)
双指针思路: pre指向前一个元素,取一个count,统计单个元素的频率,cur和pre相等的时候,count++,如果count和maxcount相等的时候,就把数值放入结果数组。
定义一个pre指针,一个count,一个maxcount,一个结果集。
递归三部曲:
- 参数和返回值:结果记在结果集里面,所以不需要返回值。
- 终止条件:遇到空的话就返回。
- 单层递归逻辑:中序遍历。
左:向左递归遍历。
中:统计元素出现的频率。注意处理pre是NULL的情况。
如果pre指向的数值和cur的数值相等,count++,如果pre数值和cur数值不相等,count=1。pre要跟在cur的后面:pre = cur。
如果count==maxcount,把当前的数值放入结果集中。
如果count>maxcount,更新maxcount,清空result数组,把目前count对应的值放入结果集。
👆避免两次遍历二叉树。
右:向右递归遍历。
题解
class Solution {
public:
int count = 0;
int maxCount = 0;
TreeNode* pre = NULL;
vector<int> result; // 在遍历的过程中更新maxCount和result,从而避免需要遍历两次二叉树
void searchBST(TreeNode* cur) {
if (cur == NULL) return;
searchBST(cur->left);
if (pre == NULL) {
count = 1;
} else if(pre->val == cur->val) {
count++;
} else {
count = 1;
}
pre = cur;
if (count == maxCount) {
result.push_back(cur->val);
}
if (count > maxCount) {
maxCount = count;
result.clear();
result.push_back(cur->val);
}
searchBST(cur->right);
return;
}
vector<int> findMode(TreeNode* root) {
result.clear();
searchBST(root);
return result;
}
};
class Solution:
def __init__(self):
self.maxCount = 0
self.count = 0
self.pre = None
self.result = []
def searchBST(self, cur):
if not cur:
return
self.searchBST(cur.left)
if self.pre is None:
self.count = 1
elif self.pre.val == cur.val:
self.count += 1
else:
self.count = 1
self.pre = cur
if self.count == self.maxCount:
self.result.append(cur.val)
if self.count > self.maxCount:
self.maxCount = self.count
self.result = [cur.val]
self.searchBST(cur.right)
return
def findMode(self, root: Optional[TreeNode]) -> List[int]:
self.result = []
self.searchBST(root)
return self.result
反思
注意对maxcount的维护,可以积累一下。这样就不需要遍历两次二叉树了,而是在一次遍历的过程中来不断维护maxcount和结果集。
236. 二叉树的最近公共祖先
题目链接
思想
从下往上遍历,处理顺序可以从下往上遍历,可以用回溯来实现。应该用后序遍历,左右中,回溯到中。
注意审题,每个节点的数值都是不一样的。

如图所示,p和q的相对位置有两种情况,第一种情况很好想到;第二种情况,p是q的祖先,那么p是p和q的最近公共祖先。
递归三部曲:
- 参数和返回值
- 确定终止条件:如果传回来的是空 return root;如果找到了p或者q,就把root返回。
- 单层递归逻辑:
左:向左遍历,记得用一个参数接返回值。
右:向右遍历,使用参数接返回值。
中:
如果两个返回值都不为空,此事的root就是最近公共祖先,把root返回。
如果left空,right不为空,返回right。
如果left不为空,right为空,返回left。
如果两边都为空,返回NULL。
题解
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 and right != NULL) return root;
if (left == NULL && right != NULL) return right;
if (left != NULL && right == NULL) return left;
else return NULL;
}
};
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if root == q or root == p or root == None:
return root
left = self.lowestCommonAncestor(root.left, p, q)
right = self.lowestCommonAncestor(root.right, p, q)
if left is not None and right is not None:
return root
if left is None:
return right
return left
反思
注意分析两种情况。
1146

被折叠的 条评论
为什么被折叠?



