剑指offer--所有链表题型题解及代码,Java语言

1、树的子结构

题目描述

输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

思路

  • 递归判断,其中一个函数hasSubTree判读一个树是不是另一个树的子树,函数isSubTree判断两棵树是不是相等,根节点相等则判断左右子树是否相等。

代码

/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        if(root1==null||root2==null)
            return false;
        else return HasSubtree(root1.left,root2)||HasSubtree(root1.right,root2)||isSubTree(root1,root2);
    }
    
    private boolean isSubTree(TreeNode root1,TreeNode root2){
        if(root2==null)
            return true;
        if(root1==null)
            return false;
        else if(root1.val==root2.val)
            return isSubTree(root1.left,root2.left)&&isSubTree(root1.right,root2.right);
        return false;
    }
}

2、重建二叉树

题目描述

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

思路

  • 前序遍历数组pre数组,中序遍历数组in数组,pre数组第一个数组即为根节点,遍历in数组找到根节点所在位置,则in数组中根节点左边即为左子树,右边即为右子树。

代码

/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        TreeNode root = reConstructBinaryTreeAs(pre,0,pre.length-1,in,0,in.length-1);
        return root;
    }
    private TreeNode reConstructBinaryTreeAs(int [] pre,int preStart,int preEnd,int [] in,int inStart,int inEnd){
        if(preEnd<preEnd||inEnd<inStart)
            return null;
        TreeNode root = new TreeNode(pre[preStart]);
        for(int i=inStart;i<=inEnd;i++){
            if(in[i]==root.val){
                root.left = reConstructBinaryTreeAs
                    (pre,preStart+1,preStart+i-inStart,in,inStart,i-1);
                root.right = reConstructBinaryTreeAs
                    (pre,i-inStart+preStart+1,preEnd,in,i+1,inEnd);
                break;
            }
        }
        return root;
    }
}

3、二叉树的镜像

题目描述

操作给定的二叉树,将其变换为源二叉树的镜像。

输入描述

二叉树的镜像定义:源二叉树
8
/
6 10
/ \ /
5 7 9 11
镜像二叉树
8
/
10 6
/ \ /
11 9 7 5

思路

  • 交换左右子树,递归交换直到左右子树都为空。

代码

/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public void Mirror(TreeNode root) {
        if(root==null||(root.left==null&&root.right==null))
            return;
        TreeNode p = root.left;
        root.left = root.right;
        root.right = p;
        Mirror(root.left);
        Mirror(root.right);
    }
}

3、从上往下打印二叉树

题目描述

从上往下打印出二叉树的每个节点,同层节点从左至右打印。

思路

  • 借助一个队列,一个list,根节点入队列,每次从队列中弹出一个元素,将这个元素add进list中,同时在队列中把当前节点的左右子树入队列。

代码

import java.util.ArrayList;
import java.util.Queue;
import java.util.LinkedList;
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
        ArrayList<Integer> list = new ArrayList<>();
        Queue<TreeNode> queue = new LinkedList<>();
        if(root==null) return list;
        queue.add(root);
        while(!queue.isEmpty()){
            TreeNode k = queue.poll();
            list.add(k.val);
            if(k.left!=null)
                queue.add(k.left);
            if(k.right!=null)
                queue.add(k.right);
        }
        return list;
    }
}

4、二叉搜索树的后序遍历序列

题目描述

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。

思路

后序遍历,根节点为最后一个元素,左子树的元素都小于根节点,右子树的元素都大于根节点,遍历数组。

代码

public class Solution {
    public boolean VerifySquenceOfBST(int [] sequence) {
        int n = sequence.length;
        if(n==0) return false;
        return rejudge(sequence,0,n-1);
    }
    
    private boolean rejudge(int [] sequence,int start,int len){
        if(start>=len)
            return true;
        int n = sequence[len];
        int i=start;
        while(i<=n&&sequence[i]<sequence[len])
            i++;
        for(int j=i;j<=len;j++){
            if(sequence[j]<sequence[len])
                return false;
        }
        return rejudge(sequence,0,i-1)&&rejudge(sequence,i,len-1);
    }
    
}

5、二叉树中和为某一值的路径

题目描述

输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)

思路

  • 先序遍历 递归

代码

import java.util.ArrayList;
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    private ArrayList<ArrayList<Integer>> list1 = new ArrayList<ArrayList<Integer>>();
    private ArrayList<Integer> list2 = new ArrayList<>();
    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
        if(root==null)
            return list1;
        list2.add(root.val);
        target = target-root.val;
        if(target==0&&root.left==null&&root.right==null)
            list1.add(new ArrayList<Integer>(list2));
        FindPath(root.left,target);
        FindPath(root.right,target);
        list2.remove(list2.size()-1);
        return list1;
    }
}

6、二叉树的深度

题目描述

输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。

思路

  • 递归,往下递归一层,左子树和右子树的深度都加1,然后返回值更大的。

代码

/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public int TreeDepth(TreeNode root) {
        if(root==null)
            return 0;
        int left = TreeDepth(root.left);
        int right = TreeDepth(root.right);
        return Math.max(left,right)+1;
    }
}

7、平衡二叉树

题目描述

输入一棵二叉树,判断该二叉树是否是平衡二叉树。

思路

平衡二叉树:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

代码

public class Solution {
    public boolean IsBalanced_Solution(TreeNode root) {
        if(root==null)
            return true;
        return Math.abs(treeDepth(root.left)-treeDepth(root.right))<=1&&
            IsBalanced_Solution(root.left)&&IsBalanced_Solution(root.right);
    }
    
    private int treeDepth(TreeNode root){
        if(root==null)
            return 0;
        else return Math.max(treeDepth(root.left),treeDepth(root.right))+1;
    }
}

8、二叉树的下一个结点

题目描述

给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。

思路

分析二叉树的下一个节点,一共有以下情况:
1.二叉树为空,则返回空;
2.节点右孩子存在,则设置一个指针从该节点的右孩子出发,一直沿着指向左子结点的指针找到的叶子节点即为下一个节点;
3.节点不是根节点。如果该节点是其父节点的左孩子,则返回父节点;否则继续向上遍历其父节点的父节点,重复之前的判断,返回结果。

代码

/*
public class TreeLinkNode {
    int val;
    TreeLinkNode left = null;
    TreeLinkNode right = null;
    TreeLinkNode next = null;

    TreeLinkNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {
    public TreeLinkNode GetNext(TreeLinkNode pNode)
    {
        if(pNode.right!=null){
            TreeLinkNode p = pNode.right;
            if(p.left!=null){
                while(p.left!=null)
                    p = p.left;
            }
            return p;
        }
        else if(pNode.next!=null&&pNode.next.left == pNode)
            return pNode.next;
        else if(pNode.next!=null){
            TreeLinkNode p1 = pNode;
            while(p1.next.left!=p1){
                p1 = p1.next;
                if(p1.next==null)
                    return null;
            }
            return p1.next;
        }
        return null;
    }
}

9、对称的二叉树

题目描述

请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。

思路

代码

10、按之字形顺序打印二叉树

题目描述

请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。

思路

代码

11、把二叉树打印成多行

题目描述

从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。

思路

代码

12、序列化二叉树

题目描述

*请实现两个函数,分别用来序列化和反序列化二叉树

二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过 某种符号表示空节点(#),以 ! 表示一个结点值的结束(value!)。

二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。*

思路

代码

13、二叉搜索树的第k个结点

题目描述

给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4。

思路

代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值