leetcode二叉树整理2

404.左叶子之和

思路:找左叶子,怎么判断一个节点是左叶子?当前节点的左孩子如果没有左孩子和右孩子,那么这个节点左孩子就是左叶子
因此,只需要遍历二叉树即可,在遍历到中节点的时候,要进行的操作是,判断中节点的左孩子是否为左叶子
我在这题中用的是层次遍历

class Solution {
    
    
    public int sumOfLeftLeaves(TreeNode root) {
    
    
        Deque<TreeNode> deque = new LinkedList<>();
        if(root==null) return 0;
        int res = 0;
        deque.offerLast(root);
        while(deque.size()!=0){
    
    
            TreeNode node = deque.pollFirst();
            if(node.left!=null&&node.left.left==null&&node.left.right==null){
    
    
                res += node.left.val;
            }
            if(node.left!=null){
    
    
                deque.offerLast(node.left);
            }
            if(node.right!=null){
    
    
                deque.offerLast(node.right);
            }
        }
        return res;
    }
}

513.找树左下角的值

最后一行最左边的值,这道题用层序遍历时最简单的,而且层序遍历是迭代,用递归反而麻烦hhh

112. 路径总和

回溯,同找树所有路径的那个,只不过是在判断是否要加入的时候,要加一下该路径总和
这个题是要看有没有,找到直接整个函数可以返回了
所以这个题的回溯也可以在主函数里递归来写,不需要统计result

class Solution {
    
        
    public boolean hasPathSum(TreeNode root, int sum) {
    
    
        if(root==null) return false;
        sum -= root.val;
        if(sum==0&&root.left==null&&root.right==null) return true;
        return hasPathSum(root.left,sum)||hasPathSum(root.right,sum);

    }
}

113. 路径总和II

回溯,同找树所有路径的那个,只不过是在判断是否要加入的时候,要加一下该路径总和
这个题是要找到所有,要回溯遍历整个树

106. 从中序与后序遍历序列构造二叉树

通过X序遍历和X序遍历构造回二叉树
注:前序和后序是不能构造回二叉树的
中序:左中右 后序:左右中 因此,拿到两个序的值之后,一起遍历,遍历到出现不同为止,那么中序的不同的第一个就是中间的节点(不中节点就是后续最后一个节点),然后左边的值是左子树的中序遍历,右边的值是右子树的中序遍历。后序遍历也可以获取到左子树的后序遍历和右子树的后序遍历,这样,再次调用这个函数换源左右子树即可,注意边界条件,ok!

class Solution {
    
    
    public TreeNode buildTree(int[] inorder, int[] postorder) {
    
    
        if(inorder.length==0) return null;
        int rootVal = postorder[postorder.length-1];
        TreeNode root = new TreeNode(rootVal);
        int res=0;
        for(int i=0;i<inorder.length;i++){
    
    
            if(inorder[i]==rootVal){
    
    
                res=i;
                break;
            }
        }
        int[] inorderleft = (int[])Arrays.copyOfRange(inorder,0,res);
        int[] inorderright = (int[])Arrays.copyOfRange(inorder,res+1,inorder.length);
        int[] postorderleft = (int[])Arrays.copyOfRange(postorder,0,res);
        int[] postorderright = (int[])Arrays.copyOfRange(postorder,res,inorder.length-1);
        root.left = buildTree(inorderleft,postorderleft);
        root.right = buildTree(inorderright,postorderright);
        return root;
    }
}

105. 从前序与中序遍历序列构造二叉树

详细思路同上,没有太大差别

654.最大二叉树

这个题就是根据题目要求构造就完了,找好中间节点,左右子树依靠递归完成就行

class Solution {
    
    
    public int getMax(int[] nums){
    
    
        int index = 0;
        int maxValue = nums[0];
        for(int i=1;i<nums.length;i++){
    
    
            if(nums[i]>maxValue){
    
    
                index = i;
                maxValue = nums[i];
            }
        }
        return index;
    }

    public TreeNode constructMaximumBinaryTree(int[] nums) {
    
    
       if(nums.length == 0) return null;
       int index = getMax(nums);
       TreeNode node = new TreeNode(nums[index]);
       int[] left = Arrays.copyOfRange(nums,0,index);
       int[] right = Arrays.copyOfRange(nums,index+1,nums.length);
       node.left = constructMaximumBinaryTree(left);
       node.right = constructMaximumBinaryTree(right);
        return node;
    }
}

617.合并二叉树

这个题就是按照题意,去生成树,然后三种情况,两个都为null;一个为null,一个不为空;两个都有怎么处理

class Solution {
    
    
    public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
    
    
        if(t1==null&&t2==null) return null;
        if(t1==null||t2==null) return t1==null?t2:t1;
        TreeNode node = new TreeNode(t1.val+t2.val);
        node.left = mergeTrees(t1.left,t2.left);
        node.right = mergeTrees(t1.right,t2.right);
        return node;
    }
}

700.二叉搜索树中的搜索

二叉搜索树的性质,中节点左子树的值都小于中节点,右子树都大于中节点
然后再树中找给定的值,就是如果相等就返回root节点,小于就去左子树找,大于就去右子树找

class Solution {
    
    
    public TreeNode searchBST(TreeNode root, int val) {
    
    
        if(root == null) return null;
        if(root.val == val) return root;
        if(root.val>val) return searchBST(root.left,val);
        return searchBST(root.right,val);
    }
}

98.验证二叉搜索树

二叉搜索树的性质,中节点左子树的值都小于中节点,右子树都大于中节点,左右节点也都是二叉搜索树,所以一个二叉搜索树,中序遍历(左中右),获得的遍历结果应该是从小到大的

class Solution {
    
    
    List<Integer> list = new LinkedList<>();
    public void inorder(TreeNode root){
    
    
        if(root == null) return;
        inorder(root.left);
        list.add(root.val);
        inorder(root.right);
    }
    public boolean isValidBST(TreeNode root) {
    
    
        if(root==null) return true;
        inorder(root);
        for(int i=1;i<list.size();i++){
    
    
            if(list.get(i-1)>=list.get(i)) return false;
        }
        return true;
    }
}

530.二叉搜索树的最小绝对差

所以根据上题,中序遍历(左中右),获得的遍历结果应该是从小到大的,直接依次计算获得最小差值即可。
我这个没有向上个题一样直接写中序遍历拿一个List,而是使用中序的迭代方法

扫描二维码关注公众号,回复: 12731473 查看本文章
class Solution {
    
    
    public int getMinimumDifference(TreeNode root) {
    
    
        Deque<TreeNode> deque = new LinkedList<>();
        TreeNode cur = root;
        TreeNode pre = null;
        int res = Integer.MAX_VALUE;
        while(cur != null || deque.size()!=0){
    
    
            if(cur!=null){
    
    
                deque.offerLast(cur);
                cur = cur.left;
            }else{
    
    
                cur = deque.pollLast();
                if(pre!=null){
    
    
                    res = Math.min(cur.val-pre.val,res);
                }
            pre = cur;
            cur = cur.right;
            }
        }
        return res;
    }
}

501.二叉搜索树中的众数

进阶:你可以不使用额外的空间吗?(假设由递归产生的隐式调用栈的开销不被计算在内)
中序遍历的同时,记录最大连续数,当前值连续数,当前值(我在算法里用的是List,实际,不应该可以节省空间的),最大连续值
如果当前值连续数超越最大连续数,替换,使用中序遍历,保证同一个值都出现在一起

class Solution {
    
    
    List<Integer> list = new LinkedList<>();
    int maxCount = 0;
    int count = 0;
    TreeNode pre = null;
    public void searchBST(TreeNode root){
    
    
        if(root==null) return;
        searchBST(root.left);
        if(pre == null) count=1;
        else if(pre.val==root.val) count++;
        else count=1; 
        pre = root;
        if(count == maxCount) list.add(root.val);
        if(count> maxCount){
    
    
            maxCount = count;
            list.clear();
            list.add(root.val);
        }
        searchBST(root.right);
    }
    public int[] findMode(TreeNode root) {
    
    
        searchBST(root);
        int[] res = new int[list.size()];
        for(int i=0;i<list.size();i++){
    
    
            res[i] = list.get(i);
        }
        return res;
    }
}

236. 二叉树的最近公共祖先

思路:如果当前节点是它的公共祖先,那么这两个值一定一个在该节点左边,一个在该节点右边,如果在该节点的同一个子树上,那么它一定不是最近公共祖先

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;
        else if(left==null||right==null) return left==null?right:left;
        else return null;
    }
}

235. 二叉搜索树的最近公共祖先

这个题可以依赖二叉搜索树的性质,通过这两个值的大小去判断应该在哪个子树上,如果两个树一大一小,那么这个节点就是最近公共祖先

class Solution {
    
    
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
    
    
      if(root.val>Math.max(p.val,q.val)){
    
    
          return lowestCommonAncestor(root.left,p,q);
      }if(root.val<Math.min(p.val,q.val)){
    
    
          return lowestCommonAncestor(root.right,p,q);
      }
      return root;
    }
}

701.二叉搜索树中的插入操作

找到合适的位置插入并不难,问题是插入完了之后,你要不要去把这个树变成一个平衡二叉搜索树,如果这个题不需要变成一个平衡二叉搜索树,那你只用找到插入的位置即可,依然是利用搜索树性质,左小右大。

class Solution {
    
    
    public TreeNode insertIntoBST(TreeNode root, int val) {
    
    
        if(root==null) return new TreeNode(val);
        if(root.val>val){
    
    
            root.left = insertIntoBST(root.left,val);
        }else{
    
    
            root.right = insertIntoBST(root.right,val);
        }
        return root;
    }
}

450.删除二叉搜索树中的节点

删除节点有三种情况:
1.没找到,那就直接返回
2.删除的节点在叶子,那就直接删除
3.节点不在叶子,这种的是比较麻烦的,需要重构二叉搜索树
3.1节点不在叶子,但是该节点缺了左子树或者右子树,那么直接将不缺的那一边子树上移,补上该节点缺口
3.2节点不在叶子,且左子树右子树均在:选择左子树或右子树根节点作为新节点,用左子树根节点为例,则给右子树在左子树的右支找到一个位置,直接让右子树那一颗树放在该位置即可

class Solution {
    
    
     public TreeNode insertIntoBST(TreeNode root,TreeNode node) {
    
    
        if(node==null) return root;
        if(root==null) return node;
        if(root.val>node.val){
    
    
            root.left = insertIntoBST(root.left,node);
        }else{
    
    
            root.right = insertIntoBST(root.right,node);
        }
        return root;
    }
    public TreeNode deleteNode(TreeNode root, int key) {
    
    
        if(root==null) return null;
        if(root.val==key&&root.left==null&&root.right==null) return null;
        else if(root.val==key&&(root.left==null||root.right==null)){
    
    
            return root.left==null?root.right:root.left;
        } else if(root.val==key){
    
    
            TreeNode right = root.right;
            right = insertIntoBST(root.right,root.left.right);
            TreeNode node = new TreeNode(root.left.val,root.left.left,right);
            return node;
        }
        if(root.val>key){
    
    
            root.left = deleteNode(root.left,key);
        }else{
    
    
            root.right = deleteNode(root.right,key);
        }
        return root;
    }
}

669. 修剪二叉搜索树

这个题目的要求是,如果树中元素有相对结构,那么这个结构不应该被改变,所以不要想着去遍历一遍树,然后截一段,再重新生成树,这样会破坏原本结构
因此,思路:递归,递归条件如下
1.如果节点为null 返回null
2.如果节点值大于最大值,则该节点和右子树一定都不满足条件,直接返回左子树处理的结果就行了
如果节点小于最小值,则该节点和左子树一定都不满足条件,直接返回右子树处理的结果就行了
3.如果不满足,说明节点值在区间内,保留该节点,继续处理它的左右子树即可

class Solution {
    
    
    public TreeNode trimBST(TreeNode root, int low, int high) {
    
    
        if(root==null) return root;
        if(root.val>high) return trimBST(root.left,low,high);
        if(root.val<low) return trimBST(root.right,low,high);
        root.left = trimBST(root.left,low,high);
        root.right = trimBST(root.right,low,high);
        return root;
    }
}

108.将有序数组转换为二叉搜索树

这回是构造二叉树了,而且要求的是二叉平衡搜索树
这个题的难点在于,怎么去找中间节点?保证左右子树平衡?
方法是:使用最中间的位置的值,作为中间节点,值左边左子树,值右边右子树,这样构造出来的树一定是二叉平衡搜索树。一般来讲,大家构造二叉搜索树的时候,也都会取中间节点构造树

class Solution {
    
    
    public TreeNode traversal(int[] nums,int left,int right){
    
    
        if(left>right) return null;
        int mid = left+(right-left)/2;
        TreeNode node = new TreeNode(nums[mid]);
        node.left=traversal(nums,left,mid-1);
        node.right= traversal(nums,mid+1,right);
        return node;
    }
    public TreeNode sortedArrayToBST(int[] nums) {
    
    
        TreeNode node = traversal(nums,0,nums.length-1);
        return node;
    }
}

538.把二叉搜索树转换为累加树

给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。
根据累加树定义:我们不难想到,遍历顺序应该是右中左然后遍历到的节点的值应该加上上一个遍历的节点的值。明白怎么做,就很好做了。

class Solution {
    
    
    int count=0;
    public TreeNode convertBST(TreeNode root) {
    
    
        if(root==null) return null;
        root.right = convertBST(root.right);
        count+=root.val;
        root.val=count;
        root.left = convertBST(root.left);
        return root;
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_38857307/article/details/114373035