第一次做该部分的题目
530.二叉搜索树的最小绝对差
文章链接:代码随想录 (programmercarl.com)
思路:先用中序转换为一个数组,然后在数组中用双指针依次遍历计算
看完文章后的思路:不需要开辟额外的空间,跟验证二叉搜索树一样,直接使用双指针
Java递归代码:
class Solution {
private int result = Integer.MAX_VALUE;
TreeNode pre = null;
public int getMinimumDifference(TreeNode root) {
if(root == null){
return 0;
}
help(root);
return result;
}
private void help(TreeNode root){
//确定终止条件
if(root == null){
return;
}
//左中右
help(root.left);
if(pre != null){
result = Math.min(result,Math.abs(root.val - pre.val));
}
pre = root;
help(root.right);
}
}
501.二叉搜索树中的众数
文章链接:代码随想录 (programmercarl.com)
思路:中序遍历,将数放入到map当中,key为值,value为频次,然后最大频次的数为众数(可能有多个数)
看完文章后的反思:
(1)卡哥的思路目前为双指针,看到一个评论,说的比较透彻
评论:这个双指针妙的地方主要还是在思想,类似于动态规划的状态转移,并不等到全部遍历完才确定maxCount,而是每次遍历都确定目前已遍历序列的maxCount,因为下次遍历是在目前序列的基础上,所以下次maxCount的状态可以由目前转移过去,总的来说就是一个状态迭代的思想。
状态迭代的思想很关键,总是能确定局部最优解,在处理海量数据以及分布式数据时能实时给出局部最优结果,并且有较低的时间复杂度。
(2)list.clear():删除所有元素
Java代码(自己的思路):用的map,然后通过entrySet()的getValue等等,leecode上可以通过
class Solution {
Map<Integer,Integer> mymap = new HashMap<>();
public int[] findMode(TreeNode root) {
help(root);
int maxcount = 0;
int count = 0;
for(Map.Entry<Integer,Integer> getmap: mymap.entrySet()){
if(getmap.getValue() >= maxcount){
maxcount = getmap.getValue();
}
}
List<Integer> result = new ArrayList<>();
for(Map.Entry<Integer,Integer> getmap: mymap.entrySet()){
if(getmap.getValue() == maxcount){
result.add(getmap.getKey());
}
}
int[] res = new int[result.size()];
for(int i = 0; i < result.size();i++){
res[i] = result.get(i);
}
return res;
}
//获取元素频次的map
private void help(TreeNode root){
if(root == null){
return;
}
help(root.left);
if(mymap.containsKey(root.val)){
mymap.put(root.val,mymap.get(root.val) + 1);
}
else{
mymap.put(root.val,1);
}
help(root.right);
}
}
Java代码递归法(双指针):
class Solution {
TreeNode pre = null;
private int maxcount = 0;
private int count = 0;
List<Integer> resList;
public int[] findMode(TreeNode root) {
resList = new ArrayList<>();
help(root);
int[] res = new int[resList.size()];
for(int i = 0; i < resList.size();i++){
res[i] = resList.get(i);
}
return res;
}
private void help(TreeNode root){
if(root == null){
return;
}
help(root.left);
int rootValue = root.val;
//计数
if(pre == null || rootValue != pre.val){
count = 1;
}
else{
count++;
}
//更新resList
if(count == maxcount){//如果此时rootValue的频次达到最高
resList.add(rootValue);
}
else if(count > maxcount){//初始化的maxcount为0
//更新maxcount
maxcount = count;
resList.clear();
resList.add(rootValue);
}
pre = root;
help(root.right);
}
}
236.二叉树的最近公共祖先
文章链接:代码随想录 (programmercarl.com)
思路:使用后序遍历(左右中),采用双指针,向上返回,知道两个指针指向同一节点(想当然,思路错误)
反思:Moment大佬讲解的很详细,递归流程如下(这个就是递归的思路,重要!!!)
(1) 如果当前结点 root 等于 NULL,则直接返回 NULL (2) 如果 root 等于 p或者 q ,那这棵树一定返回 p 或者 q(3) 然后递归左右子树,因为是递归,使用函数后可认为左右子树已经算出结果,用 left 和 right 表示 (4) 此时若left为空,那最终结果只要看 right;若 right 为空,那最终结果只要看 left (5) 如果 left 和 right 都非空,因为只给了 p 和 q 两个结点,都非空,说明一边一个,因此 root 是他们的最近公共祖先 (6) 如果 left和 right 都为空,则返回空(其实已经包含在前面的情况中了)
作者:Moment
链接:https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/solutions/93282/c-jing-dian-di-gui-si-lu-fei-chang-hao-li-jie-shi-/
来源:力扣(LeetCode)
其他反思:
(1)看到该题讨论里lighter大佬提出的一个思路:我的想法是递归函数返回当前节点以及其左右子树包含的PQ节点数量,若某个节点第一次计数达到2,说明就是最近的公共祖先。(以后可以尝试写写)
(2)为什么这边没有在最后加return语句:因为中处理把所有情况都考虑进去了
Java递归法代码:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null){
return null;
}
if(root == p || root == q){//只有一个p或者q
return root;
}
//递归,拆黑盒,后序遍历
TreeNode left = lowestCommonAncestor(root.left,p,q);
TreeNode right = lowestCommonAncestor(root.right,p,q);
if(left != null && right != null){
return root;
}
else if(left != null && right == null){
return left;
}
else if(left == null && right != null){
return right;
}
else{
return null;
}
}
}