题目描述:
输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。
原题链接:
思路:
- 新建一个头指针head作为合并后链表的头指针。
- 比较L1,L2两链表的头节点大小,将较小者赋值给head.next,同时较小者向后移动一位p=p.next。
- 将head向后移动一位head=head.next。
- 依次重复23步骤,直到L1或L2为空。
- 将L1和L2中不为空链表直接赋给head。
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode head = new ListNode(-1); //合并后链表的头指针
ListNode tail = head; //建立临时指针赋值及向后移动
while(l1 != null && l2 != null){
if (l1.val < l2.val){ //比较val值大小
tail.next = l1;
l1 = l1.next; //向后移动一位
}
else {
tail.next = l2;
l2 = l2.next;
}
tail = tail.next; //向后移动一位
}
tail.next = l1 == null ? l2 : l1; //将剩余链表直接赋值给tail
return head.next;
}
问题1:不建立临时指针有什么影响?
头指针在循环过程中不断赋值向后移动导致最后返回的变成了尾指针,而不是题目中要求的头指针
问题2:为什么一开始不直接对tail进行赋值运算,而是对tail.next进行赋值运算?
如果直接对tail进行赋值运算,直接返回head可行吗?
不可行,直接对tail进行赋值运算会导致tail指针本身的丢失
使用内存(堆栈)对其进行解释,链表指针本质上是一个类new出来的对象,JVM中对象存储在栈中(实际存储的是堆中对应内存地址),而对象封装的变量是存储在堆中,new对象实际上是指向堆中的对象封装的变量
当直接对tail进行赋值运算时,将L1地址赋给tail会导致tail直接指向堆中L1的地址,而head本身没有任何变化,最后返回的仍然是最初的模样
当对tail.next进行赋值运算时,相当于将L1的地址赋给了tail.next,并不会导致tail指针本身指向变化,后续链表的全部变化head始终为该链表的头指针,最后返回head.next即可
总结:
- 链表指针本质上是对象
- 记录一个链表头指针时不能单纯对头指针进行赋值,会导致指针丢失