Leetcode树题目集合

  1. 二叉树的最大深度
class Solution {
    public int maxDepth(TreeNode root) {
        if(root==null) 
        return 0;
        int left=maxDepth(root.left);
        int right=maxDepth(root.right);
        return left>right?left+1:right+1;
    }
}
  1. 平衡二叉树
    这里想平衡二叉树的定义,左子树和右子树深度不超过1
    同时左子树和右子树也是平衡二叉树
class Solution {
    public boolean isBalanced(TreeNode root) {
        if(root==null)
            return true;
      
       int  deepLeft=deep(root.left);
       int  deepRight=deep(root.right);
        int sub=deepLeft-deepRight;
        if(sub>1||sub<-1)
            return false;
         if(!isBalanced(root.left))
            return false;
        if(!isBalanced(root.right))
            return false;
        return true;
    }
    public int deep(TreeNode root)
    {
        if(root==null)
         return 0;
        int left=deep(root.left);
        int right=deep(root.right);
        return left>right?left+1:right+1;
    }
}

一样的做法,更简洁的写法:

private boolean result = true;
public boolean isBalanced(TreeNode root) {
    maxDepth(root);
    return result;
}
public int maxDepth(TreeNode root) {
    if (root == null) return 0;
    int l = maxDepth(root.left);
    int r = maxDepth(root.right);
    if (Math.abs(l - r) > 1) result = false;
    return 1 + Math.max(l, r);
}
  1. 二叉树的直径
class Solution {
    private int max;
    public int diameterOfBinaryTree(TreeNode root) {
           depth(root);
           return max;

    }   
    public int depth(TreeNode root){
        if(root==null)
            return 0;
        int left=depth(root.left);
        int right=depth(root.right);
        max=Math.max(max,left+right);
        return Math.max(left,right)+1;
    }
}
  1. 翻转二叉树
    递归:
class Solution {
    public TreeNode invertTree(TreeNode root) {
        if(root==null||(root.left==null&&root.right==null))
                return root;
            TreeNode temp=root.right;
            root.right=invertTree(root.left);
            root.left=invertTree(temp);
        return root;
    }   
}
  1. 合并二叉树
class Solution {
   public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
    if (t1 == null && t2 == null) return null;
    if (t1 == null) return t2;
    if (t2 == null) return t1;
    TreeNode root = new TreeNode(t1.val + t2.val);
    root.left = mergeTrees(t1.left, t2.left);
    root.right = mergeTrees(t1.right, t2.right);
    return root;
}
}
  1. 路径总和
class Solution {
    public boolean hasPathSum(TreeNode root, int sum) {       
            if(root==null)
            return false;
            if(root.right==null&&root.left==null&&root.val==sum)
                return true;
            return hasPathSum(root.left,sum-root.val)||hasPathSum(root.right,sum-root.val);
    }
}

437路径总和 III
两种方法 双重递归

class Solution {
    //双层递归
    public int pathSum(TreeNode root, int sum) {
        if(root==null)
            return 0;
        int  count=path(root,sum)+pathSum(root.left,sum)+pathSum(root.right,sum);    //所有结点作为根节点递归
        return count;        
    }
    public int path(TreeNode root,int sum){     //以所在根节点为递归
        if(root==null)
            return 0;
        int count=0;
        if(sum==root.val)
            count++;
        count+=path(root.left,sum-root.val)+path(root.right,sum-root.val);
        return count;
    }
}
  1. 另一个树的子树
class Solution {
    public boolean isSubtree(TreeNode s, TreeNode t) {
        if(s==null&&t==null)
        {System.out.println("true1");
            return true;}
        if(s==null||t==null)
        {
            System.out.println("false1");
            return false;
        }
        if(s.val==t.val)
        {
            isSubtree(s.left,t.left);
            isSubtree(s.right,t.right);
            System.out.println("true2");
            return true;
        }
        else
        {
            isSubtree(s.left,t);
            isSubtree(s.right,t);
           
        }
        System.out.println("false 2");
        return false;
        
    }
    }

这种做法是错误的 尽管有true返回,但最终返回的是false

正确做法

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isSubtree(TreeNode s, TreeNode t) {
        if (s == null) return false;
    return isSubtree1(s, t) || isSubtree(s.left, t) || isSubtree(s.right, t);
        
    }
    private boolean isSubtree1(TreeNode s, TreeNode t){
            if(s==null&&t==null)
                return true;
            if(s==null||t==null)
                return false;
            if(s.val==t.val)
           { 
            return isSubtree1(s.left,t.left)&&isSubtree1(s.right,t.right);
            //体会这样写与isSubtree1(s.left,t.left); isSubtree1(s.right,t.right); return true的区别;
            }
            else 
            return false;

            /*又可写成  if(s.val!=t.val) return false;  
          /*  return isSubtree1(s.left,t.left)&&isSubtree1(s.right,t.right); */
    }
}
  1. 对称二叉树
    两种做法,递归和迭代:
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root==null)
            return true;
        return isSymmetric1(root.left,root.right);
          
    }
    public boolean isSymmetric1(TreeNode left,TreeNode right){
        if(left==null&&right==null)
            return true;
        if(left==null||right==null)
            return false;
        if(left.val!=right.val)
            return false;
        return isSymmetric1(left.left,right.right)&&isSymmetric1(left.right,right.left);
    }
   
}

迭代:用队列实现

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
 
public boolean isSymmetric(TreeNode root) {
   Queue<TreeNode> q=new LinkedList<TreeNode>();
   if(root==null)
    return true;
   q.add(root.right);
   q.add(root.left);
   while(!q.isEmpty()){
       TreeNode t1=q.poll();
       TreeNode t2=q.poll();
       if(t1==null&&t2==null)   continue;
       if(t1==null||t2==null)   return false;
       if(t1.val!=t2.val)       return false;
       q.add(t1.left);
       q.add(t2.right);
       q.add(t2.left); 
       q.add(t1.right);
   }
    return true;
}
}
  1. 二叉树的最小深度
class Solution {
    public int minDepth(TreeNode root) {
        if(root==null)
            return 0;
        int left=minDepth(root.left);
        int right=minDepth(root.right);
        if(left==0||right==0)            //注意这里的情况,只有左子树或者只有右子树
            return left+right+1;
        return Math.min(left,right)+1;
    }
}

230 Kth Smallest Element in a BST
用栈或着队列,这是一颗搜索二叉树,注意大小规则
解法一:

class Solution {
    private int count=0;
    private int sum=0;
    public int kthSmallest(TreeNode root, int k) {
        mid(root,k);
        return sum;
    }
    private int mid(TreeNode root,int k){
        if(root==null)  
            return 0;
        mid(root.left,k);
        count++;
        if(count==k)
            sum=root.val;
        mid(root.right,k);
        return 0;
    }
}

解法二:

class Solution {
    public int kthSmallest(TreeNode root, int k) {
        Stack<TreeNode> stack=new Stack<>();
            int count=0,ret=1;
        while(root!=null||!stack.isEmpty()){
            while(root!=null){
                stack.push(root);
                root=root.left;
                }
                root=stack.pop();
                if(count<k-1){
                    count++;
                }
                else
                {
                    ret=root.val;
                    break;
                }
            root=root.right;
        }
            return ret;

    }
}
  1. 左叶子之和
class Solution {
    public int sumOfLeftLeaves(TreeNode root) {
        if(root==null)
            return 0;
        return sumOfLeftLeaves1(root.left,true)+sumOfLeftLeaves1(root.right,false);
        
    }
    private int sumOfLeftLeaves1(TreeNode root,boolean left)
    {
        if(root==null)
            return 0;
        int sum=0;
        if(root.left==null&&root.right==null&&left)     //左叶子结点
            sum=root.val;   
        int leftv=sumOfLeftLeaves1(root.left,true);
        int right=sumOfLeftLeaves1(root.right,false);
        return sum+leftv+right;
    }
}
  1. 最长同值路径
    ✳稍微有点难理解
class Solution {
    private int count=0;
    public int longestUnivaluePath(TreeNode root) {
        arrowLenght(root);
        return count;
        
    }
    private int arrowLenght(TreeNode node)
   {
       if(node==null)
            return 0;
        int left=arrowLenght(node.left);   //父节点的值等于与左右节点比较后,左右节点继续延续(延续后只能返回左右节点的一个分支,所以函数的返回值是, Math.max(currentLeft,currentRight))
        int right=arrowLenght(node.right);
        int currentLeft=0,currentRight=0;
        if(node.left!=null&&node.left.val==node.val)
            currentLeft=left+1;
        if(node.right!=null&&node.right.val==node.val)
            currentRight=right+1;
        count=Math.max(count,currentLeft+currentRight);     //*比较一下与存储起来的值哪个大/
        return Math.max(currentLeft,currentRight);  //返回给父节点的值父节点不能将左右节点的延续都包括进来,

   }
}

538:
解法1:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode convertBST(TreeNode root) {
        TreeNode temp=root;
        List<Integer> list=new ArrayList<>();
        Stack<TreeNode> stack1=new Stack<>();
        Stack<TreeNode> stack=new Stack<>();
        while(root!=null||!stack.isEmpty()){
            while(root!=null){
                stack.push(root);
                root=root.left;
            }
            root=stack.pop();
            list.add(root.val);
            stack1.push(root);
                root=root.right;
        }
        // Collections.reverse(stack);
        Collections.reverse(list);
        while(!stack1.isEmpty()){
            int sum=0;
        for(int i=0;list.get(i)>stack1.peek().val;i++)
        {
            sum+=list.get(i);
        }
        System.out.println(sum);
        stack1.pop().val+=sum;
        }
        return temp;
    }
}

递归方法:

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

栈方法:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
  
    public TreeNode convertBST(TreeNode root) {
        TreeNode temp=root;
      Stack<TreeNode> stack=new Stack();
      int sum=0;
      while(root!=null||!stack.isEmpty()){
          while(root!=null)
          {
            stack.push(root);
            root=root.right;
          }
          root=stack.pop();
          sum+=root.val;
          root.val=sum;
          root=root.left;
      }
      return temp;
    }
}
  1. 打家劫舍 III
class Solution {
    public int rob(TreeNode root) {
    if (root == null) return 0;
    int val1 = root.val;
    if (root.left != null) val1 += rob(root.left.left) + rob(root.left.right);      
    if (root.right != null) val1 += rob(root.right.left) + rob(root.right.right);
    int val2=rob(root.left)+rob(root.right); //打劫这一个加上间隔的一个多 还是直接打劫下一个左右结点
    return Math.max(val1,val2);
}
}
  1. 二叉树中第二小的节点
class Solution {
    public int findSecondMinimumValue(TreeNode root) {
        //问题可以转化为求左右子树的最小值,
        //如果左右子树最小值都大于根节点的值取较小的值。
        //其他情况取左右子树较大的值。
        if(root==null)
            return -1;
        if(root.left==null&&root.right==null)
            return -1;
        int left=root.left.val;
        int right=root.right.val;
        if(root.val==left)
            left=findSecondMinimumValue(root.left);
        if(root.val==right)
            right=findSecondMinimumValue(root.right);
        if(left!=-1&&right!=-1)
            return Math.min(left,right);
        if(left!=-1)
            return left;
        return right;

        
    }
}
  1. 二叉树的层平均值
    层次遍历
class Solution {
    public List<Double> averageOfLevels(TreeNode root) {
        List<Double> result=new ArrayList<>();
        Queue<TreeNode> queue=new LinkedList<>();
        queue.add(root);
       while(!queue.isEmpty()){
         int size=queue.size();
         double sum=0;
            for(int i=0;i<size;i++){
                TreeNode temp=queue.poll();
                sum+=temp.val;
                if(temp.left!=null)
                    queue.add(temp.left);
                if(temp.right!=null)
                    queue.add(temp.right);
            }
        result.add(sum/size);
                
        }
        return result;
    }
 
}
  1. 找树左下角的值
class Solution {
    //深度搜索
    public int findBottomLeftValue(TreeNode root) {
        Queue<TreeNode> queue=new LinkedList<>();
        queue.add(root);
        while(!queue.isEmpty()){
                 root=queue.poll();
                 if(root.right!=null)queue.add(root.right);
                 //左结点最后取出,所以先加右结点再加左
                 if(root.left!=null)queue.add(root.left);
        }
        return root.val;
    }
}
  1. 二叉树的前序遍历
非递归实现二叉树前序遍历,用栈的数据结构,结点先进后出
public List<Integer> preorderTraversal(TreeNode root) {
    List<Integer> ret = new ArrayList<>();
    Stack<TreeNode> stack = new Stack<>();
    stack.push(root);
    while (!stack.isEmpty()) {
        TreeNode node = stack.pop();
        if (node == null) continue;
        ret.add(node.val);
        stack.push(node.right); // 先右后左,保证左子树先遍历
        stack.push(node.left);
    }
    return ret;
}
  1. 二叉树的后序遍历
/*
非递归实现
前序遍历为 root -> left -> right,
后序遍历为 left -> right -> root。
可以修改前序遍历成为 root -> right -> left,
那么这个顺序就和后序遍历正好相反
再用reverse颠倒结果
*/
class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer>   ret=new ArrayList<>();
        Stack<TreeNode> stack=new Stack<>();
        if(root==null)  return ret;
        stack.add(root);
        while(!stack.isEmpty()){
            TreeNode temp=stack.pop();
            ret.add(temp.val);
            if(temp.left!=null)
                stack.add(temp.left);
            if(temp.right!=null)            
                stack.add(temp.right); 
        }
        Collections.reverse(ret);
        return ret;
    }
}
  1. 二叉树的中序遍历
    非递归实现
    ①mirrors遍历
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer>   ret=new ArrayList<>();
        TreeNode current=root;
        while(current!=null){
           if(current.left==null){          //如果左子树为空
               ret.add(current.val);            //假如当前结点并进入右边节点    
               current=current.right;   
           }
           else{                            //左子树不为空,找他的前序结点
               TreeNode temp=current.left;
    while(temp.right!=null&&temp.right!=current){  
         //找最右结点,并且不是指向current的最右结点
                    temp=temp.right;
               }
            if(temp.right==null){           //最右结点还没指向current时
                temp.right=current;
                current=current.left;       //进入他的左子树
            }
            else{                            //要是指向了当前节点自己
                temp.right=null;
                ret.add(current.val);        //打印curr的值
                current=current.right;       //左边遍历完毕 ,遍历右边
            }

           }
        }
        return ret;
    }
}

public List<Integer> inorderTraversal(TreeNode root) {
    List<Integer> ret = new ArrayList<>();
    if (root == null) return ret;
    Stack<TreeNode> stack = new Stack<>();
    TreeNode cur = root;
    while (cur != null || !stack.isEmpty()) {
        while (cur != null) {
            //要先加入所有的左孩子结点
        stack.push(cur);
        cur = cur.left;
        }
        TreeNode node = stack.pop();
        ret.add(node.val);
        cur = node.right;
    }
    return ret;
}
  1. 修剪二叉搜索树
class Solution {
    public TreeNode trimBST(TreeNode root, int L, int R) {
       if(root==null)   return null;
       if(root.val>R)   return trimBST(root.left,L,R);
       if(root.val<L)   return trimBST(root.right,L,R);
       root.left=trimBST(root.left,L,R);
       root.right=trimBST(root.right,L,R);
       return root;
    }
}
  1. 把二叉搜索树转换为累加树
①迭代解法:
class Solution {
  
    public TreeNode convertBST(TreeNode root) {
        TreeNode temp=root;
      Stack<TreeNode> stack=new Stack();
      int sum=0;
      while(root!=null||!stack.isEmpty()){
          //按从大到小的顺序出栈就可以
          while(root!=null)
          {
            stack.push(root);
            root=root.right;
          }
          root=stack.pop();
          sum+=root.val;
          root.val=sum;
          root=root.left;
      }
      return temp;
    }
}

②递归解法:

private int sum = 0;
public TreeNode convertBST(TreeNode root) {
    traver(root);
    return root;
}
private void traver(TreeNode node) {
    if (node == null) return;
    traver(node.right);
    sum += node.val;
    node.val = sum;
    traver(node.left);
}
  1. 二叉搜索树的最近公共祖先
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
       if(root.val>p.val&&root.val>q.val)
        return lowestCommonAncestor(root.left,p,q);
       if(root.val<p.val&&root.val<q.val)
        return lowestCommonAncestor(root.right,p,q);
        return root;
    }
}
  1. 二叉树的最近公共祖先
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);
    return left == null ? right : right == null ? left : root;
    }
}
  1. 将有序数组转换为二叉搜索树
    分治算法
class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
    return toBST(nums, 0, nums.length - 1);
}

private TreeNode toBST(int[] nums, int sIdx, int eIdx){
    if (sIdx > eIdx) return null;
    int mIdx = (sIdx + eIdx) / 2;
    TreeNode root = new TreeNode(nums[mIdx]);
    root.left =  toBST(nums, sIdx, mIdx - 1);
    root.right = toBST(nums, mIdx + 1, eIdx);
    return root;
}
}
  1. 有序链表转换二叉搜索树
    跟上一题相似,快慢指针找出链表的中点
class Solution {
    public TreeNode sortedListToBST(ListNode head) {
        if(head==null)
            return null;
        if (head.next == null) 
        return new TreeNode(head.val);
        ListNode pre=findMid(head);
        ListNode mid=pre.next;
        pre.next=null;
        TreeNode root=new TreeNode(mid.val);
        root.left=sortedListToBST(head);
        root.right=sortedListToBST(mid.next);   
        return root;
    }
    public ListNode findMid(ListNode head){
        ListNode slow=head,fast=head.next;
        ListNode pre=head;
        while(fast!=null&&fast.next!=null){
            pre=slow;
            slow=slow.next;
            fast=fast.next.next;
        }
        return pre;
    }
}
  1. 两数之和 IV - 输入 BST
    其他解法:找中子数
class Solution {
    public boolean findTarget(TreeNode root, int k) {
      Set<Integer> set=new HashSet<>();
      return helper(set,root,k);
    }
    public boolean helper(Set set,TreeNode root,int k){
        if(root==null)
            return false;
        if(set.contains(k-root.val))
            return true;
        set.add(root.val);
        return helper(set,root.left,k)||helper(set,root.right,k);
    }
    
}
  1. 二叉搜索树的最小绝对差
class Solution {
    private int min=Integer.MAX_VALUE;
    private TreeNode pre=null;
    public int getMinimumDifference(TreeNode root) {
        helper(root);
        return min;
    }
    public void helper(TreeNode root){
        if(root==null)
            return;
        helper(root.left);

        if(pre!=null)   {
            //按递增顺序遍历的,pre结点的值总是小于root结点
        min=Math.min(min,root.val-pre.val);
        }
        pre=root;           ///上一步的结点
        helper(root.right);
        return;
    }

}
  1. 二叉搜索树中的众数
class Solution {
   private int curCnt = 1;
   private int maxCnt = 1;
   private TreeNode preNode = null;
   List<Integer> list=new ArrayList<>();
    public int[] findMode(TreeNode root) {
         findList(root);
    int[] ret = new int[list.size()];
    int idx = 0;
    for (int num : list) {
        ret[idx++] = num;
    }
    return ret;

    }
    private void findList(TreeNode root){
        if(root==null)
            return;
        findList(root.left);
        if(preNode!=null)
        if(root.val==preNode.val)
            curCnt++;
        else
            curCnt=1;
        if(curCnt==maxCnt)
        list.add(root.val);
        if(curCnt>maxCnt)
        {
            maxCnt=curCnt;
            list.clear();
            list.add(root.val);
        }
        preNode=root;
        findList(root.right);
        return;
    }
    }
  1. 实现 Trie (前缀树)
    ⭐有点难,有空再code一下
class TreeNode{
    public TreeNode[] children=new TreeNode[26];
    public boolean isEnd;
     /*public TreeNode(){//
        children = new TreeNode[26];//子节点数组长度26,0:‘a’,1:‘b’.....
        isEnd= false;
    }*/
}
class Trie {
    TreeNode root;
    private int  count=0;
    // Trie next;
    /** Initialize your data structure here. */
    public Trie() {
        root=new TreeNode();
    }

    /** Inserts a word into the trie. */
    public void insert(String word) {
        TreeNode p=root;
        for (int i = 0; i <word.length(); i++) {
            char curent=word.charAt(i);
            if(p.children[curent-'a']==null){
                p.children[curent-'a']=new TreeNode();
            }
            p=p.children[curent-'a'];
        }
        p.isEnd=true;
    }

    /** Returns if the word is in the trie. */
    public boolean search(String word) {
        TreeNode p=root;
        for(int i=0;i<word.length();i++)
        {
            char curent=word.charAt(i);
            if(p.children[curent-'a']!=null)
                p=p.children[curent-'a'];
            else
                return false;
        }
        return p.isEnd;
    }

    /** Returns if there is any word in the trie that starts with the given prefix. */
    public boolean startsWith(String prefix) {
        TreeNode p=root;
        for(int i=0;i<prefix.length();i++)
        {
            char curent=prefix.charAt(i);
            if(p.children[prefix.charAt(i)-'a']!=null)
                p=p.children[curent-'a'];
            else
                return false;
        }
        if(p.isEnd==true)
            count++;
        getCount(p);
        System.out.println(count);
        return true;
    }
    public void getCount(TreeNode p) {
        if(p==null)
            return;
        for(int i=0;i<26;i++){
            if(p.children[i]!=null){
                if(p.children[i].isEnd==true)
            {
                count++;
                continue;
            }
                else 
                getCount(p.children[i]);
            }
        }
        return;
    }
 
}
  1. 键值映射
    ⭐有点难
class MapSum {

    private class Node {
        Node[] child = new Node[26];
        int value;
    }

    private Node root = new Node();

    public MapSum() {

    }

    public void insert(String key, int val) {
        insert(key, root, val);
    }

    private void insert(String key, Node node, int val) {
        if (node == null) return;
        if (key.length() == 0) {
            node.value = val;
            return;
        }
        int index = indexForChar(key.charAt(0));
        if (node.child[index] == null) {
            node.child[index] = new Node();
        }
        insert(key.substring(1), node.child[index], val);
    }

    public int sum(String prefix) {
        return sum(prefix, root);
    }

    private int sum(String prefix, Node node) {
        if (node == null) return 0;
        if (prefix.length() != 0) {
            int index = indexForChar(prefix.charAt(0));
            return sum(prefix.substring(1), node.child[index]);
        }
        int sum = node.value;
        for (Node child : node.child) {
            sum += sum(prefix, child);
        }
        return sum;
    }

    private int indexForChar(char c) {
        return c - 'a';
    }
    }

猜你喜欢

转载自blog.csdn.net/weixin_44137260/article/details/105844731