Leetcode 21. 合并两个有序链表 面试变形:合并+去重

文章介绍了如何合并两个已排序的链表,包括不使用虚拟头节点的方法、采用虚拟头节点的优化方法以及递归去重的解决方案。
摘要由CSDN通过智能技术生成

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;
        }
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值