剑指offer(16-18)题解

16题解–合并两个排序的链表

题目描述

输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

思路解析

这题逻辑其实本质上就是归并排序,就是元素的存取以及边界的判断条件有不同。
这里先贴上别人对于归并排序的一张模拟图:
在这里插入图片描述

其次就是懂得list.next=null与list=null的区别,list.next=null,说明当前list中还是有值的,所以我们会出现漏值的情况,list=null就说明当前list已经为空了值已经全部取出来了。
最后就是懂得在list==null的情况下我们在做list=list.next的运算时会报空指针异常,这个相信都能理解,所以我们必须加上条件判断语句避免报错。

源代码

import java.util.ArrayList;
import java.util.List;
public class Solution {
/*    public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
   public ListNode Merge(ListNode list1,ListNode list2) {
        List<ListNode>list3=new ArrayList<ListNode>();
       if(list1==null)
        	return list2;
        if(list2==null)
        	return list1;
        if(list1==null&&list2==null)
        	return null;
        //这里如果写list.next!=null会出现元素没有取干净的情况
        while(list1!=null||list2!=null)
        {
        		if(list1.val<list2.val)
        		{
        			list3.add(new ListNode(list1.val));
        			//这里主要配合上面我们写的list!=null想对应的,如果不进行判断就会报空指针异常
        			if(list1.next!=null)
        				list1=list1.next;
        			//这里主要是与下面我们检查链表是否还有剩余元素,如果这已经是该链表的最后一个元素
        			//那么我们就需要将这个链表置为空,否则我们在下面重新遍历剩余链表元素时,这个剩余
        			//元素会被再次计入,导致重复
        			else 
        			{
        				list1=null;
        				break;
        			}
        		}
        		else 
        		{
        			list3.add(new ListNode(list2.val));
        			if(list2.next!=null)
        				list2=list2.next;
        			else 
        			{
        				list2=null;
        				break;
        			}
        		}
        }
         while(list1!=null)
        {
        	list3.add(new ListNode(list1.val));
        	if(list1.next!=null)
        		list1=list1.next;
        	//如果next为空就说明已经是最后一个元素了,并且我们上面已经添加过该元素了,所以直接跳出循环即可
        	else 
        		break;
        }
        while(list2!=null)
        {
        	list3.add(new ListNode(list2.val));
        	if(list2.next!=null)
        		list2=list2.next;
        	else 
        		break;
        }
        //重新将我们的链表串起来
        for(int i=0;i<list3.size()-1;i++)
        	list3.get(i).next=list3.get(i+1);
        return list3.get(0);
    }
}

17题解–树的子结构

题目描述

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

思路解析

这题博主主要是看了题解之后写的
首先我们要注意一个概念就是子树和子结构这两个概念
举个例子来说明:
在这里插入图片描述
这就代表我们只需要保证root2是root1的一个部分就够。
接下来是大体思路:


我们首先要创建一个函数用来帮助我们判断root1的当前节点下是否存在root2这样一个子结构。
我们递归去检查root1的左孩子与root2的左孩子是否也符合同理右孩子
在这个检查过程中只要出现一个值不对应,就直接说明不存在,直接返回。
如果出现root2为空的情况就说明已经递归比较到最后发现root2空了说明所有的元素都已经比较匹配了所以说明存在这样一个子结构。
但是如果出现root1比root2先空的情况就说明不存在这样一个子结构。


主函数我们从root1的根节点开始与root2进行比较,如果匹配成功那么久返回为TRUE,如果匹配不成功,那么我们就递归用根节点的左右孩子去匹配,一直匹配到最后,再将flag返回即可。

源代码

/**
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) {
		boolean flag=false;
		if(root1==null||root2==null)
			return false;
		//匹配子结构
		if(root1.val==root2.val)
			flag=hasroot(root1, root2);
		//递归匹配左孩子与子结构
		if(!flag) 
            flag=HasSubtree(root1.left, root2);
        //递归匹配右孩子与子结构
		if(!flag) 
            flag=HasSubtree(root1.right, root2);
		return flag;
    }
	public boolean hasroot(TreeNode root1,TreeNode root2)
	{
	    //root2先空说明已经全部匹配出来,说明存在该子结构
		if(root2==null)
			return true;
	    //root1先空就说明还未匹配出子结构,但是root1已经没有元素了,说明root2剩下的元素都不存在
	    //所以不存在该子结构
		if(root1==null)
			return false;
        if(root1.val!=root2.val)
            return false;
        //递归减产两者对应的左右孩子节点
		return hasroot(root1.left, root2.left)&&hasroot(root1.right, root2.right);
	}
}

18题解–二叉树的镜像

题目描述

操作给定的二叉树,将其变换为源二叉树的镜像。
输入描述:
二叉树的镜像定义:源二叉树
在这里插入图片描述

思路解析

主要思想就是递归调用稍微注意一下终止条件root=null,否则root为null还在执行交换的动作会报空指针异常。

源代码

public class Solution {
  public void Mirror(TreeNode root) {
		if(root==null)
            return;
		TreeNode node=root.left;
		root.left=root.right;
		root.right=node;
		Mirror(root.left);
		Mirror(root.right);
    }
}

都看到这里了,如果觉得对你有帮助的话,可以关注博主的公众号,新人up需要你的支持。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值