剑指offer_27,28and练习

剑指 Offer 27. 二叉树的镜像

当遍历到root的左右结点时,交换左右结点,就是镜像操作了,所以最经典的还是递归操作了。

本题和226. 翻转二叉树为一种题型,方法相同。

class Solution {
    public TreeNode mirrorTree(TreeNode root) {
        //递归
        if(root == null){return null;}
        TreeNode left = mirrorTree(root.left); 
        TreeNode right = mirrorTree(root.right);
        root.left = right;
        root.right = left;
        return root;
    }
}

第二种就是用栈,队列都可以,和递归一样,就是遍历所有结点,交换左右结点。

class Solution {
    public TreeNode mirrorTree(TreeNode root) {
        if(root == null){return null;}
        Deque<TreeNode> stack = new LinkedList<TreeNode>();
        stack.push(root);
        while(!stack.isEmpty()){
           TreeNode node = stack.pop();
           if(node.left!=null){stack.push(node.left);}
           if(node.right!=null){stack.push(node.right);}
           TreeNode cur = node.left;
           node.left = node.right;
           node.right=cur;
        }
        return root;
        }
}
剑指 Offer 28. 对称的二叉树

递归,check函数,判断子树的左结点等于右节点,右节点等于左节点,即对称

class Solution {
    public boolean isSymmetric(TreeNode root) {
        return check(root, root);
    }

    public boolean check(TreeNode p, TreeNode q) {
        if (p == null && q == null) {
            return true;
        }
        if (p == null || q == null) {
            return false;
        }
        return p.val == q.val && check(p.left, q.right) && check(p.right, q.left);
    }
}

迭代,对root的两个子树,进行对称比较。

/**
 * 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;
        }
        Deque<TreeNode> deque = new LinkedList<TreeNode>(); 
        deque.add(root.left);
        deque.add(root.right);
        while(!deque.isEmpty()){
            TreeNode left = deque.remove();
            TreeNode right = deque.remove();
            if(left==null&&right==null){
                continue;
            }
            if(left==null||right==null){
                return false;
            }
            if(left.val!=right.val){
                return false;
            }
            deque.add(left.left);  //核心:左子树的左节点和右子树的右节点
            deque.add(right.right); //左子树的右节点和右子树的左节点进行比较
            deque.add(left.right);
            deque.add(right.left);
        }
        return true;
    }
}
104. 二叉树的最大深度

最大深度其实就和层序遍历一样,从根节点依次往下遍历,每一层全部遍历,找到下一层的所有结点,根据结点的多少,来删除当前层并添加下一层。

class Solution {
    public int maxDepth(TreeNode root) {
        if(root == null){
            return 0;
        }
        int max = 0;
        Deque<TreeNode> deque= new LinkedList<>();
        deque.add(root);
        while(!deque.isEmpty()){
            max++;
            int size = deque.size();
            for(int i =0;i<size;i++){
                TreeNode node  = deque.remove();
                if(node.right!=null){deque.add(node.right);}
                if(node.left!=null){deque.add(node.left);}
            }
        }
        return max;
    }
}

看了看递归,唉,为什么就学不会递归呢。(好简单)

class Solution {
    public int maxDepth(TreeNode root) {
        return root == null?0:Math.max(maxDepth(root.left),maxDepth(root.right))+1;
    }
}
112. 路径总和

这个题感觉就像是求两数之和一样,只不过不是数组了,变成了栈或队列。首先,先用栈搞了一遍,确实用时和内存都不是太好。

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if(root == null){
            return false;
        }
        Stack<TreeNode> stack1 = new Stack<TreeNode>();
        Stack<Integer> stack2 = new Stack<Integer>();
        //用两个栈一个存结点一个存数值
        stack1.push(root);
        stack2.push(root.val);
        while(!stack1.isEmpty()){
            TreeNode node = stack1.pop();
            int sum = stack2.pop();
            if(node.left==null&&node.right==null&&sum==targetSum){
                return true;
            }//结点往下遍历,sum累加。
            if(node.right!=null){
                stack1.push(node.right);
                stack2.push(sum+node.right.val);
            }
            if(node.left!=null){
                stack1.push(node.left);
                stack2.push(sum+node.left.val);
            }
        }
        return false;
    }
}

队列与上面栈同理.

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if(root == null){
            return false;
        }
        Deque<TreeNode> queue1 = new LinkedList<TreeNode>();
        Deque<Integer> queue2 = new LinkedList<Integer>();
        queue1.add(root);
        queue2.add(root.val);
        while(!queue1.isEmpty()){
            TreeNode node = queue1.remove();
            int sum = queue2.remove();
            if(node.left==null&&node.right==null&&sum==targetSum){
                return true;
            }
            if(node.left!=null){
                queue1.add(node.left);
                queue2.add(sum+node.left.val);
            }if(node.right!=null){
                queue1.add(node.right);
                queue2.add(sum+node.right.val);
            }
        }
    return false;
    }
}

递归

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if(root == null){
            return false;
        }
        if(root.left == null && root.right == null){
            return targetSum == root.val;
        }
        return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);
    }//让tar每向下遍历一次,tar减去当前root.val,直到相等为true。
}

二叉树有很多分类,二叉搜索树便是其中一种,二叉搜索树有一个最关键的定义就是:根节点/父节点的左子树上的节点都比根节点/父节点小,而右子树上的节点都比根节点/父节点要大。所以根据这个做题就可以变得简单一些。

700. 二叉搜索树中的搜索

因为左子树小于根节点,右子树大于根节点,所以根据这些来判断当前结点和val的值,找到后直接输出root,即是余下的子树。(核心就是val大于根节点,往右走,val小于根节点,往左走)。

class Solution {
    public TreeNode searchBST(TreeNode root, int val) {

        while(root!=null&&root.val!=val){
            if(root.val>val){
                root = root.left;
            }
            else if(root.val<val){
                root = root.right;
            }
        }
        return root;
    }
}

当然,也可以递归判断。

class Solution {
    public TreeNode searchBST(TreeNode root, int val) {
        if (root == null) {
            return null;
        }
        if (val == root.val) {
            return root;
        }
        return searchBST(val < root.val ? root.left : root.right, val);
    }
}
01. 二叉搜索树中的插入操作

本题也是如此,先判断根节点和value的大小,然后依次往下继续搜索,如果当前结点大于value,往左,否则往右,直到下一节点为空,然后插入新节点并且值为value。

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

递归

class Solution {
    public TreeNode insertIntoBST(TreeNode root, int val) {
        if(root == null){
            return new TreeNode(val);
        }
       TreeNode node = root;
       if(node.val>val){
       node.left = insertIntoBST(node.left,val);
       }
       else{
       node.right = insertIntoBST(node.right,val);
       }
       return root;
    }
}
653. 两数之和 IV - 输入二叉搜索树

和数组的两数之和也类似,

创建一个哈希表和一个队列,将根节点加入队列中,然后执行以下步骤:

从队列中取出队头,假设其值为 x;检查哈希表中是否存在 k−x,如果存在,返回 True;否则,将该节点的左右的非空子节点加入队尾;重复以上步骤,直到队列为空;如果队列为空,说明树上不存在两个和为 k 的节点,返回 False。

class Solution {
    public boolean findTarget(TreeNode root, int k) {
        if(root == null){
            return false;
        }
        Set<Integer> set = new HashSet<>();
        Deque<TreeNode> deque = new LinkedList<>();
        deque.offer(root);
        while(!deque.isEmpty()){
            TreeNode node = deque.poll();
            if(set.contains(k-node.val)){
                return true;
            }
            set.add(node.val);
            if(node.left!=null){
                deque.offer(node.left);
            }
            if(node.right!=null){
                deque.offer(node.right);
            }
        }
        return false;
    }
}

递归

class Solution {
    Set<Integer> set = new HashSet<Integer>();

    public boolean findTarget(TreeNode root, int k) {
        if (root == null) {
            return false;
        }
        if (set.contains(k - root.val)) {
            return true;
        }
        set.add(root.val);
        return findTarget(root.left, k) || findTarget(root.right, k);
    }
}

因为二叉搜索树是左<中<右的,而中序遍历是左中右的,所以二叉搜索树中序遍历之后的结果,就是一个升序数组,而升序数组就是前面的两数之和的计算了。

class Solution {
    List<Integer> list = new ArrayList<Integer>();

    public boolean findTarget(TreeNode root, int k) {
        inorderTraversal(root);
        int left = 0, right = list.size() - 1;
        while (left < right) {
            if (list.get(left) + list.get(right) == k) {
                return true;
            }
            if (list.get(left) + list.get(right) < k) {
                left++;
            } else {
                right--;
            }
        }
        return false;
    }

    public void inorderTraversal(TreeNode node) {
        if (node == null) {
            return;
        }
        inorderTraversal(node.left);
        list.add(node.val);
        inorderTraversal(node.right);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值