Leetcode 21. 合并两个有序链表 面试变形:合并+去重
- 为了解法更通用,我默认两条链表为非递减链表
方法1:不采用虚拟头节点
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
if (list1 == null) return list2;
if (list2 == null) return list1;
// 默认list1为第一个数小的链表
if (list1.val > list2.val) {
return mergeTwoLists(list2, list1);
}
ListNode head = list1, tail = list1;
ListNode p1 = list1.next;
ListNode p2 = list2;
while (p1 != null && p2 != null) {
System.out.println(p1.val + " == " + p2.val + " == " + tail.val);
// 先判断待插入的节点是否会与尾节点相同,若会,删除
if (p1.val == tail.val) {
p1 = p1.next;
continue;
}
if (p2.val == tail.val) {
p2 = p2.next;
continue;
}
if (p1.val < p2.val) {
tail.next = p1;
tail = p1;
p1 = p1.next;
} else {
tail.next = p2;
tail = p2;
p2 = p2.next;
}
}
// 最后的while循环是因为,可能某条链表剩余的元素中仍然包含重复元素
if (p1 == null) {
while (p2 != null) {
if (p2.val != tail.val) {
tail.next = p2;
tail = p2;
}
p2 = p2.next;
}
} else {
while (p1 != null) {
if (p1.val != tail.val) {
tail.next = p1;
tail = p1;
}
p1 = p1.next;
}
}
return head;
}
}
方法二:采用虚拟头节点
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
// 采用虚拟头节点写法
// 假定链表为非递减链表
ListNode dummyHead = new ListNode();
ListNode tail = dummyHead;
ListNode p1 = list1, p2 = list2;
while (p1 != null && p2 != null) {
// 找到p1中的某个值得最后一个节点
while (p1.next != null && p1.val == p1.next.val) p1 = p1.next;
// 找到p2中的某个值得最后一个节点
while (p2.next != null && p2.val == p2.next.val) p2 = p2.next;
// 找到两个链表中第一个不相同的节点
// 有相同默认跳过list1的节点
if (p1.val == p2.val) {
p1 = p1.next;
}
if (p1 == null) {
break;
}
if (p1.val < p2.val) {
tail.next = p1;
tail = p1;
p1 = p1.next;
} else {
tail.next = p2;
tail = p2;
p2 = p2.next;
}
}
if (p1 == null) {
while (p2 != null) {
if (p2.val != tail.val) {
tail.next = p2;
tail = p2;
}
p2 = p2.next;
}
} else {
while (p1 != null) {
if (p1.val != tail.val) {
tail.next = p1;
tail = p1;
}
p1 = p1.next;
}
}
return dummyHead.next;
}
}
方法3:递归
摘自:https://leetcode.cn/problems/merge-two-sorted-lists/solutions/1333622/he-bing-by-handsometaoa-bc42/评论区
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
// 递归
// 去重1 如果发现单个链表有重复数字,直接跳到最后一个
while (list1 != null && list1.next != null && list1.val == list1.next.val) {
list1 = list1.next;
}
while (list2 != null && list2.next != null && list2.val == list2.next.val) {
list2 = list2.next;
}
if (list1 == null && list2 == null) return null;
if (list1 == null) {
list2.next = mergeTwoLists(list1, list2.next);
return list2;
}
if (list2 == null) {
list1.next = mergeTwoLists(list1.next, list2);
return list1;
}
if (list1.val < list2.val) {
list1.next = mergeTwoLists(list1.next, list2);
return list1;
} else if (list1.val > list2.val) {
list2.next = mergeTwoLists(list1, list2.next);
return list2;
} else { // 去重2
list1.next = mergeTwoLists(list1.next, list2.next);
return list1;
}
}
}