【算法】【线性表】【链表】删除排序链表中的重复元素 II

发布时间 2024-01-12 07:16:50作者: 酷酷-

1  题目

给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。

示例 1:

输入:head = [1,2,3,3,4,4,5]
输出:[1,2,5]

示例 2:

输入:head = [1,1,1,2,3]
输出:[2,3]

提示:

  • 链表中节点数目在范围 [0, 300] 内
  • -100 <= Node.val <= 100
  • 题目数据保证链表已经按升序 排列

2  解答

跟上一个题有一点类似,但还是不一样,它重复的元素要全部删除掉哈:

/**
 * 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 deleteDuplicates(ListNode head) {
       // 如果链表为空或者next为空 直接返回
        if (head == null || head.next == null) {
            return head;
        }
        // 先加一个头节点,方便逻辑处理
        ListNode preHead = new ListNode(0);
        preHead.next = head;

        ListNode node = preHead;
        while (node != null) {
            // 因为我们加了一个头节点,那么当前的node肯定是需要保留的 这个理解的吧
            // 然后我们后边的两个节点
            ListNode nextOneNode = node.next;
            // 如果后边的两个节点 有一个为空 都可以break 说明后边没重复的了
            if (nextOneNode == null) break;
            ListNode nextTwoNode = nextOneNode.next;
            if (nextTwoNode == null) break;
            // flag 表示 node 后的第一个节点要不要删除
            boolean flag = false;
            // 从第二个节点开始遍历
            while (nextTwoNode != null) {
                // 如果他跟第一个节点的 val 一样 说明重复了
                if (nextTwoNode.val == nextOneNode.val) {
                    // 设置 flag = true 遍历完需要把第一个节点也删除
                    flag = true;
                    // 删除第二个节点
                    nextOneNode.next = nextTwoNode.next;
                    // 继续向后遍历删除 看看还有没有与第1个节点一样的 val
                    nextTwoNode = nextTwoNode.next;
                    // 继续
                    continue;
                }
                // 不相等了,说明与第一个节点一样的都已经删除完了 直接跳出
                break;
            }
            // flag = true 说明第一二节点有重复的,这里把第一个节点也删除掉
            if (flag) {
                node.next = nextOneNode.next;
                continue;
            }
            // 继续向后遍历
            node = node.next;
        }
        return preHead.next;
    }
}

现在链表的题就有点得心应手了,前几天做链表的题,那家伙一个简单的题,自己把自己绕的,一个多小时想不出来,现在十来分钟两道题,对于链表我就喜欢前边加个空头节点,感觉思路就清晰点儿,加油。