「这是我参与2022首次更文挑战的第10天,活动详情查看:2022首次更文挑战」
删除排序链表中的重复元素 Remove duplicates from sorted list
LeetCode传送门删除排序链表中的重复元素
原题
给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。
Given the head of a sorted linked list, delete all duplicates such that each element appears only once. Return the linked list sorted as well.
Example:
Input: head = [1,1,2]
Output: [1,2]
Input: head = [1,1,2,3,3]
Output: [1,2,3]
Constraints:
The number of nodes in the list is in the range [0, 300]. -100 <= Node.val <= 100 The list is guaranteed to be sorted in ascending order.
思考线
解题思路
如果这道题是无序的链表,要考虑如何保证节点的值是不重复的还是有一定难度的,但是这道题的前提是排好序的链表,所以我们比较容易能想出解决方案。
我是这样考虑的
-
我们先记录下
head的值设为temp -
比较
head的下一个值是否和temp相同- 若相同则说明是重复节点,我们需要把
head.next的指针指向head.next.next - 若不同,或是
head.next不存在则说明不是重复节点,我们把head指向head.next.然后把temp指向此时head的值。
- 若相同则说明是重复节点,我们需要把
-
重复以上操作直到
head为 null, 然后我们把新链表的头部返回过去,也就是原链表的头部
代码实现如下
/**
* Definition for singly-linked list.
* class ListNode {
* val: number
* next: ListNode | null
* constructor(val?: number, next?: ListNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
* }
*/
function deleteDuplicates(head: ListNode | null): ListNode | null {
if (!head) return head;
let temp = head.val; // 设置当前要比较的值。
let list = head;
while (list) {
if (list.next && list.next.val === temp) {
list.next = list.next.next;
} else {
list = list.next;
temp = list?.val ?? null;
}
}
return head;
};
但是我们再思考一下,我们真的需要设置这个temp变量吗?
其实在整个过程中我们只需要前一个跟后一个比较即可,也就是上面步骤2的操作。然后重复执行,直到 list.next为null.
我们再看一下去掉temp后的结果
function deleteDuplicates(head: ListNode | null): ListNode | null {
if (!head) return head;
let list = head;
while (list.next) {
if ( list.next.val === list.val) {
list.next = list.next.next;
} else {
list = list.next;
}
}
return head;
};
这样写我们可以省去一个变量的书写,同时也少了很多极限情况的讨论。在解题过程中,减少极限情况的讨论可以让我们更容易解题,少犯错误,同时也让代码更简洁。我们之前解题设置的虚拟头结点dummyHead也是为了减少极限的讨论。
时间复杂度
O(n): n为链表的长度。
这就是我对本题的解法,如果有疑问或者更好的解答方式,欢迎留言互动。