刷题日记18
今天依然是二叉搜索树,好吧已经连续5天刷二叉树了,是时候总结一下二叉树的题型了。
二叉搜索树的主要特点就是有序,可以看成是一个有序的数组,这样求最值,最小差值都会很容易。
530. 二叉搜索树的最小绝对差
中序遍历迭代法
class Solution {
public int getMinimumDifference(TreeNode root) {
Stack<TreeNode> s = new Stack<>();
TreeNode pre = null;
int diff = Integer.MAX_VALUE;
s.push(root);
while(!s.isEmpty()){
TreeNode node = s.peek();
if(node != null){
s.pop();
if(node.right != null) s.push(node.right);
s.push(node);
s.push(null);
if(node.left != null) s.push(node.left);
}else{
s.pop();
node = s.pop();
if(pre != null) diff = Math.min(diff, Math.abs(node.val - pre.val));
pre = node;
}
}
return diff;
}
}
中序遍历递归法
class Solution {
public int diff = Integer.MAX_VALUE;
public TreeNode pre = null;
public int getMinimumDifference(TreeNode root) {
inorder(root);
return diff;
}
public void inorder(TreeNode root){
if(root == null) return;
inorder(root.left);
if(pre != null) diff = Math.min(diff, Math.abs(pre.val - root.val));
pre = root;
inorder(root.right);
}
}
501. 二叉搜索树中的众数
一般来讲,求众数这种需要计算频率的问题,都会使用哈希表来记录频率,如下面这种算法。但这道题是二叉搜索树,一个有序的数组里,如果会出现众数,那他们一定是连续的,其实不需要一个哈希表,只需要记录前一个节点。
中序遍历,哈希表算法
class Solution {
public LinkedList<Integer> res = new LinkedList<>();
public Map<Integer, Integer> map = new HashMap<>();
public int[] findMode(TreeNode root) {
inorder(root);
return res.stream().mapToInt(Integer::valueOf).toArray();
}
public void inorder(TreeNode root){
if(root == null) return;
inorder(root.left);
map.put(root.val, map.getOrDefault(root.val, 0) + 1);
if(res.size() != 0){
if(map.get(root.val) > map.get(res.get(0))){
LinkedList<Integer> result = new LinkedList<>();
result.add(root.val);
res = result;
}
else if(root.val != res.get(0) && map.get(root.val) == map.get(res.get(0))){
res.add(root.val);
}
}else{
res.add(root.val);
}
inorder(root.right);
}
}
中序遍历,只记录前一个节点
class Solution {
public LinkedList<Integer> res = new LinkedList<>();
public TreeNode pre = null;
public int count = 0;
public int maxCount = 0;;
public int[] findMode(TreeNode root) {
inorder(root);
return res.stream().mapToInt(Integer::valueOf).toArray();
}
public void inorder(TreeNode root){
if(root == null) return;
inorder(root.left);
if(pre == null || root.val != pre.val){
count = 1;
}else{
count++;
}
if(count > maxCount){
res.clear();
res.add(root.val);
maxCount = count;
}else if(count == maxCount){
res.add(root.val);
}
pre = root;
inorder(root.right);
}
}
236. 二叉树的最近公共祖先
最开始的思路肯定是要后序遍历,因为这道题要进行从下至上的遍历,只有后序遍历能从下至上查找。
那怎么才算找到了最近公共祖先呢?也就是说有哪些情况呢?
根据以上定义,若 root 是 p,q 的 最近公共祖先 ,则只可能为以下情况之一:
- p 和 q 在 root 的子树中,且分列 root 的 异侧(即分别在左、右子树中)
- p = root,且 q 在 root 的左或右子树中
- q = root,且 p 在 root 的左或右子树中
这道题很难想出递归的终止条件,主要还是因为,一个节点自己也是自己的祖先。
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null || root == q || root == p) return root;
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
if(left == null && right == null) return null;
if(left == null && right != null) return right;
if(left != null && right == null) return left;
return root;
}
}