题目描述
存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除所有重复的元素,使每个元素 只出现一次 。
分析
输入:链表的头节点 head
输出:变换之后的链表头节点
解题思路
这道题目,我们用两种方法解,第一种方式是我上来就想到的双指针方法,另一种是官网提供的一次遍历
双指针
对于双指针的解法,我们需要定义 fast, slow 两个指针,fast会先走。
对于本题,我会让 fast 一直向前走,直到它的 val 不等于 slow 的值,才会做一些操作。
我们看张图:
第一次操作发生在 fast 从 dummyHead 走到 1 的时候,第二次是从到 3 的时候,那为了方便,我拿第二次举例。
此时 slow 指向 1,fast 指向 3,很显然我们需要做的是把 slow.next 指向 3,这样中间重复的元素都会被跳过,链表中只剩下 1 ➡️ 3 两个。
我们看下代码:
代码
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var deleteDuplicates = function (head) {
if (!head) return null;
const dummyHead = new ListNode(null, head);
let slow = dummyHead,
fast = dummyHead;
while (fast) {
// 当 fast,slow 指向不同的时候,我们进行操作,把 slow 的 next 指向 fast
// 这样链表里重复的元素只保留了一个,剩下的都被删除
if (slow.val !== fast.val) {
slow.next = fast;
slow = fast;
}
// 移动 fast
fast = fast.next;
}
// 因为最后 fast 是 null 的时候,没有把前面的元素链接 🔗 过来,所以这里做下处理
slow.next = fast;
return dummyHead.next;
};
一次遍历
这种方法是力扣官方题解,比我那个简单。
解释下,因为重复的元素都是连续的,所以只要遍历一次,然后只要发现了连续的元素,那么就在原地去把后边重复的 next 节点全部删掉,在向后遍历就可以了,我们看下代码:
代码
var deleteDuplicates = function (head) {
if (!head) return null;
let cur = head
// 我们删的是 next
while (cur.next) {
if (cur.val === cur.next.val) {
cur.next = cur.next.next;
} else {
cur = cur.next;
}
}
return head;
};