Hot100 二叉树

 94. 二叉树的中序遍历 - 力扣(LeetCode)

递归法,懂得都懂 

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
       List<Integer> res=new ArrayList<>();
        dfs(res,root);
        return res;
    }
    public void dfs(List<Integer> res,TreeNode root)
    {
        if(root==null) return;
        dfs(res,root.left);
        res.add(root.val);
        dfs(res,root.right);
    }
}

 迭代法

注意:stack!=null这样的判断是不正确的 因为stack对象已经被声明,永远都不会为空

stack==null

stack==null :stack为引用类型。"=="操作符比较的是对象的引用,而不是对象的内容。
对于stack来说,初始化赋值给了 stack 变量。这意味着 stack 引用了一个新创建的 Stack 对象,stack 不再是 null。

正确写法:stack.size()>0

101. 对称二叉树 - 力扣(LeetCode)

对称二叉树定义: 对于树中 任意两个对称节点 L 和 R ,一定有:

L.val = R.val :即此两对称节点值相等。
L.left.val = R.right.val :即 L 的 左子节点 和 R 的 右子节点 对称。
L.right.val = R.left.val :即 L 的 右子节点 和 R 的 左子节点 对称。
根据以上规律,考虑从顶至底递归,判断每对左右节点是否对称,从而判断树是否为对称二叉树。

作者:Krahets
链接:https://leetcode.cn/problems/symmetric-tree/solutions/2361627/101-dui-cheng-er-cha-shu-fen-zhi-qing-xi-8oba/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root==null) return true;
        return recur(root.left,root.right);
    }
       boolean recur(TreeNode L, TreeNode R) {
        //到达叶子节点了
        if (L == null && R == null) return true;
        //有一个为空或者两个值不相等
        if (L == null || R == null || L.val != R.val) return false;
        //向下递归 同时要满足两个比较条件:左右孩子的外层相等 左右孩子的内层相等
        return recur(L.left, R.right) && recur(L.right, R.left);
    }

}

543. 二叉树的直径 - 力扣(LeetCode)

两个关键概念

链:从子树中的叶子节点到当前节点的路径。把最长链的长度,作为 dfs 的返回值。根据这一定义,空节点的链长是 −1,叶子节点的链长是 0。

递归过程中维护的是链长。
直径:等价于由两条(或者一条)链拼成的路径。我们枚举每个 node,假设直径在这里「拐弯」,也就是计算由左右两条从下面的叶子节点到 node 的链的节点值之和,去更新答案的最大值。

  1. 案一定是某个节点的(左子树深度 + 右子树深度)最大,那么就需要遍历每一个节点,假设答案为在此节点拐弯,维护出现过的最大值。
  2. 理解-1 +1 场景可以结合节点之间的连线。叶子结点以下已经没有节点,也就没有链条了,所以为0。但是为了递归回去的返回值与+1抵消,故返回-1。+1是为了补充子节点到本节点的这根连线。可以结合case2加深理解:
    2.1. 叶子节点:下面已经无链条,下面的空节点返回 left = dfs(root.left) + 1 需要为0.
    2.2. 叶子结点的上一个节点(case2即为根节点):下面只有一条链条,则为0 + 1 = 1.
  3. 遍历每一个节点,假设最佳答案是在本节点做拐弯。那么需要 ans = Math.max(ans, left + right) 。注:子节点到本节点的连线已经在上面计算left、right时 +1补充了。
  4. dfs()的返回值。在本节点结束后,计算下一个节点(以下一个节点作为拐弯点),那么这个节点就只能是子节点场景(不能出现拐弯),返回此子节点的最长连线即 max(left, right)。
  5. class Solution {
        private int ans;
        public int diameterOfBinaryTree(TreeNode root) {
            dfs(root);
            return ans;
        }
        private int dfs(TreeNode node)
        {
            if(node==null) return -1;
            int lLen=dfs(node.left)+1;//如果node是叶子节点就会是0
            int rLen=dfs(node.right)+1;
            int length=lLen+rLen;//在本节点拐弯的最大链长
            ans=Math.max(length,ans);//更新遇见过的最大链长
    
            return Math.max(lLen, rLen); // 不在本节点拐弯,本节点下面的最大链长
        }
    }

    124. 二叉树中的最大路径和 - 力扣(LeetCode)

这道题很像,只不过上一道题dfs维护的是每个结点的最大链长,这道题要维护每个节点左右链和的最大值,以及用在每个节点拐弯的最大值来更新ans

class Solution {
    private int ans=Integer.MIN_VALUE;//比负数更小 防止有出现在只有负数的树上为0
    public int maxPathSum(TreeNode root) {
         dfs(root);
        return ans;
    }
    private int dfs(TreeNode node)
    {
        //dfs维护的是某节点的最长路径和
        //ans维护的是 这棵树上的最大路径和
        if(node==null) return 0;
        int Lsum=dfs(node.left);
        Lsum=Math.max(Lsum,0);//分支最大值为负数,则丢弃考虑分支
        int Rsum=dfs(node.right);
        Rsum=Math.max(Rsum,0);//分支最大值为负数,则丢弃考虑分支
        int sum=node.val+Lsum+Rsum;//至少保证有一个结点
        ans=Math.max(sum,ans);
        return Math.max(Lsum+node.val,Rsum+node.val);
    }
}

 108. 将有序数组转换为二叉搜索树 - 力扣(LeetCode)

感觉是二分法。。 

class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
        return bfs(nums,0,nums.length-1);
    }
    private TreeNode bfs(int[] nums ,int left,int right)
    {
        //left可以等于right嘛?可以,模拟一下就知道了
        if(left>right) return null;
        //明确一下是左闭右闭区间
        int mid=left+(right-left)/2;//防止溢出
        TreeNode node=new TreeNode(nums[mid]);
        node.left=bfs(nums,left,mid-1);
        node.right=bfs(nums,mid+1,right);
        return node;
    }
}

230. 二叉搜索树中第 K 小的元素 - 力扣(LeetCode)

1.二叉搜索树用中序是递增数组。 

2.这种找某一个值的,用一个全局变量来记录就好了。

class Solution {
    private int res,count=0;
    public int kthSmallest(TreeNode root, int k) {
        //我的思路:暴力的话中序遍历一遍放到数组里,然后返回数组
//答案
// 递归遍历时计数,统计当前节点的序号。
// 递归到第 k 个节点时,应记录结果 res 。
// 记录结果后,后续的遍历即失去意义,应提前返回。
        inOrder(root,k);
        return res;
    }
    private void inOrder(TreeNode node,int k){
        if(node==null) return;
        inOrder(node.left,k);
        count++;
        if(count==k) res=node.val;
        inOrder(node.right,k);
    }
}

114. 二叉树展开为链表 - 力扣(LeetCode) 

  1. 将左子树插入到右子树的地方
  2. 将原来的右子树接到左子树的最右边节点
  3. 考虑新的右子树的根节点,一直重复上边的过程,直到新的右子树为 null

层序遍历102. 二叉树的层序遍历 - 力扣(LeetCode)

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
      Queue<TreeNode> queue =new LinkedList<>();
      List<List<Integer>> res=new ArrayList<>();
      if(root!=null) queue.add(root);
      while(!queue.isEmpty()){
        List<Integer> tmp=new ArrayList<>();
        for(int i=queue.size();i>0;i--)
        {
            TreeNode node=queue.poll();
            tmp.add(node.val);
            if (node.left != null) queue.add(node.left);
            if (node.right != null) queue.add(node.right);
        }
        res.add(tmp);
      }  
      return res;
    }
}

相同思想:199. 二叉树的右视图 - 力扣(LeetCode) 

 437. 路径总和 III - 力扣(LeetCode)

前缀和 与 

多了一步,清除经过当前节点的状态 的回溯

体现在删除当前前缀和在map中的一次出现。

class Solution {
    int ans = 0;
    public int pathSum(TreeNode root, int targetSum) {
          // 记录路径中某个前缀和出现的次数
        Map<Long, Integer> map = new HashMap<>();
        // 防止包含根节点的时候找不到
        map.put(0L, 1);
        // 开始搜索 
        dfs(root, map, 0L, targetSum);
        // 返回值
        return ans;
    }
    private void dfs(TreeNode node, Map<Long, Integer> map, Long curSum, int targetSum)
    {
        //curSum相当于k数组那道题的presum
        if(node==null) return;
        //记录结果
        curSum += node.val;
        ans+=map.getOrDefault(curSum-targetSum,0);
        //先记录结果再加入自己
        map.put(curSum,map.getOrDefault(curSum,0)+1);
        dfs(node.left,map,curSum,targetSum);
        dfs(node.right,map,curSum,targetSum);
        //很重要的一点是回溯!!!!恢复map的状态意思是老子不在这走了!!
        //curSum不用管因为是参数 把map中加好的curSUm删除即可
         map.put(curSum, map.getOrDefault(curSum, 0)-1);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值