《剑指offer》——合并两个排序的链表

60 篇文章 3 订阅

更多2019年的技术文章,欢迎关注我的微信公众号:码不停蹄的小鼠松(微信号:busy_squirrel),也可扫下方二维码关注获取最新文章哦~

T:

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

两个有序链表的合并问题,考察的是对链表的操作。

对于此类题目,一般有两种解决思路:

  • 如果不考虑内存消耗问题,那就重新定义一个新的链表。
  • 在原有的链表上拼拼凑凑,通过调节各节点的next,合并成一个新链表,这是最常用的。但是,这只是针对链表而言,如果是两个数组进行合并的话,还是选用第一种。

这里写图片描述

对于上图,先创建一个虚的head节点,这个是方便最后的新链表返回,直接返回:
r e t u r n h e a d . n e x t ; return \quad head.next; returnhead.next;

图中的tempNode节点,按照指针的说法,总是指向合并链表的最后一个元素,方便下一个新节点的接入。
思路就是:首先找一个head的next节点,这样,tempNode就有了一个最基本的依靠。
然后对每个链表,都进行一个while循环,外层套一个大循环,大循环的终止条件,就是至少有1个链表已经循环完了。

code:

	public class Solution {

	public ListNode merge(ListNode list1, ListNode list2) {
		ListNode head = new ListNode(0);	// 指向新链表的头结点的虚头结点,方便最后的返回
		ListNode tempNode = null;	// 排序链表中的前锋指针,指向新链表的最后一个元素。
		
		// 判断是否为null
		if (list1 == null) {
			return list2;
		} else if (list2 == null) {
			return list1;
		}
		
		// 判断开头
		if (list1.val <= list2.val) {
			head.next = list1;
			list1 = list1.next;
		} else {
			head.next = list2;
			list2 = list2.next;
		}
		tempNode = head.next;
		
		// 该while 外层循环一直执行的前提,在于两个链表都没有循环到各自最后的null
		while (true) {
			
			// list1不为空,且值不大于list2的值
			while (list1 != null && list1.val <= list2.val) {
				tempNode.next = list1;
				tempNode = list1;
				list1 = list1.next;
			}
			// 如果list1循环完了,那就直接退出
			if (list1 == null) {
				break;
			}
			
			while (list2 != null && list2.val <= list1.val) {
				tempNode.next = list2;
				tempNode = list2;
				list2 = list2.next;
			}
			if (list2 == null) {
				break;
			}
		}
		// 把剩余的那部分统一拼接到最后
		if (list1 == null) {
			tempNode.next = list2;
		} else {
			tempNode.next = list1;
		}
		
		return head.next;
	}

注意:

有些判断条件的写法,还是要讲究一些技巧的:
eg: while (list1 != null && list1.val <= list2.val) {…}
这句话当中,一定要把list1 != null这个判断语句放在前面,否则有可能会造成异常:空指针错误。
因为这个判断语句是从左向右依次进行的,当第一个条件不满足时,就不再读取第二个条件。

如果放在了后面: while (list1.val <= list2.val && list1 != null) {…}
当list1 为 null时,list1.val就会出现空指针访问错误。

另外,这个题还可以用递归做,这个是在看了别人的代码之后,才发现的,受教了!!!
从没想过这种问题用递归去解决。。。。。

为了练习,我自己还是再写一个递归的版本吧。。
2015.10.29 20:43

递归code:

	/**
	 * 递归版本,为区分,本方法名字与题目给定的不同,提交的时候,注意换回来。。。
	 * 
	 *  
	 * @param args
	 */
	public ListNode merge1(ListNode list1, ListNode list2) {
		if (list1 == null) {
			return list2;
		}
		if (list2 == null) {
			return list1;
		}
		
		ListNode listNode = null;
		if (list1.val <= list2.val) {
			listNode = list1;
			listNode.next = merge1(list1.next, list2);
		} else {
			listNode = list2;
			listNode.next = merge1(list1, list2.next);
		}
		
		return listNode;
	}

更多2019年的技术文章,欢迎关注我的微信公众号:码不停蹄的小鼠松(微信号:busy_squirrel),也可扫下方二维码关注获取最新文章哦~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值