题目
题目来源:力扣(LeetCode)
存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除链表中所有存在数字重复情况的节点,只保留原始链表中 没有重复出现 的数字。
返回同样按升序排列的结果链表。
示例 1:
输入:head = [1,2,3,3,4,4,5]
输出:[1,2,5]
示例 2:
输入:head = [1,1,1,2,3]
输出:[2,3]
思路分析
双指针法
由题意可知,给定的链表已经是排好序的,因此重复的元素在链表中出现的位置是连续的,因此我们只需要对链表进行一次遍历,就可以删除重复的元素。
1、删除重复元素时链表的头节点可能会被删除,因此我们需要定义一个虚拟头节点,其后继指针指向链表的头节点:
2、定义一个 prev 指针指向虚拟头节点 dummyHead,用以将删除重复节点之后剩余的链表部分连接起来;定义一个 curr 指针,指向头节点
3、遍历链表,如果 curr 指针所指向节点的值与curr指针所指向节点的下一个节点的值相等,那么curr指针往后移动一位,prev指针则保持不动:
4、如果 curr 指针所指向节点的值与curr指针所指向节点的下一个节点的值不相等,则将prev指针所指向节点的后继指针指向 curr指针所指向节点的后一个节点,然后将 curr 指针往后移动一位:
5、接着将prev指针指向curr指针所指向的节点,然后curr指针则往后移动一位:
6、当curr.next指向null时,说明链表已经遍历完毕,链表中所有重复元素也已删除
var deleteDuplicates = function(head) {if (head == null) return null;// 定义一个虚拟头节点,其后继指针指向头节点const dummyHead = new ListNode(-1, head);// 定义 prev 指针,初始时指向虚拟头节点let prev = dummyHead;// 定义 curr 指针,指向头节点let curr = prev.next;// 遍历链表while (curr != null && curr.next != null) {// 如果 curr 指针所指向的节点值与 curr 指针所指向节点的下一个节点的值不相等if (curr.val != curr.next.val) {// prev 指针往后移动一位prev = prev.next;// curr 指针往后移动一位curr = curr.next} else {// 如果 curr 指针所指向的节点值与 curr 指针所指向节点的下一个节点的值相等while (curr != null && curr.next != null && curr.val === curr.next.val) {// curr 指针往后移动,直到找到 curr.val != curr.next.valcurr = curr.next;}prev.next = curr.next;curr = curr.next}}return dummyHead.next;};
单指针法
由于给定的链表是已经排好序的,因此重复的元素在链表中出现的位置是连续的,因此我们只需要对链表进行一次遍历,即可删除重复的元素。
由于链表的头节点也可能被删除,因此我们需要先定义一个虚拟头节点来指向链表的头节点。
然后我们定义一个 curr 指针,指向链表的虚拟头节点,随后开始遍历链表,如果当前 curr.next 与 curr.next.next 所对应节点的值相等,那么我们就将 curr.next 以及后面与之相等的节点值的所有节点全部删除。我们记录下这个元素的值 x,随后不断将 curr.next从链表中删除,直到 curr.next 为空节点或者其节点值不等于 x 为止。此时,我们已经将链表中所有节点值为 x 的节点全部删除。
如果当前 curr.next 与 curr.next.next 所对应节点的值不相等,那么说明链表中只有一个节点值为 curr.next 的节点,那么我们就可以将 curr 指针指向 curr.next,即将curr指针往后移动一位。
当遍历完这个链表,所有重复的节点也已删除,我们返回返回链表的虚拟头节点的下一个节点。
var deleteDuplicates = function(head) {if (!head) return head;// 定义一个虚拟头节点const dummyHead = new ListNode(-1, head);// 定义一个 curr 指针,指向虚拟头节点let curr = dummyHead;// 遍历链表while (curr.next && curr.next.next) {// 当前 curr.next 与 curr.next.next 所对应节点的值相等// 将 curr.next 及所有后面与之相同元素值的链表节点全部删除if (curr.next.val === curr.next.next.val) {const x = curr.next.val;while(curr.next && curr.next.val === x) {curr.next = curr.next.next;}} else {// 当前 curr.next 与 curr.next.next 所对应节点的值不相等,将 curr 指针往后移动一位curr = curr.next}}// 链表遍历完成,返回链表虚拟头节点的下一个节点return dummyHead.next;};
