题解 | 删除有序链表中重复的元素-II
删除有序链表中重复的元素-II
https://www.nowcoder.com/practice/71cef9f8b5564579bf7ed93fbe0b2024
import java.util.*; /* * public class ListNode { * int val; * ListNode next = null; * public ListNode(int val) { * this.val = val; * } * } */ public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param head ListNode类 * @return ListNode类 */ public ListNode deleteDuplicates (ListNode head) { // write code here if(head == null || head.next == null){ return head; } ListNode dummy = new ListNode(0); ListNode pre = dummy; ListNode left = head,right = head.next; while(right != null){ if(left.val != right.val){ pre.next = left; pre = pre.next; } while(right != null && right.val == left.val){ right = right.next; } if(right != null && right.next != null && right.val != right.next.val){ pre.next = right; pre = pre.next; left = right.next; right = right.next.next; }else{ if(right == null){ pre.next = null; }else if(right.next == null){ pre.next = right; break; }else{ left = right; right = right.next; } } } return dummy.next; } }
本题与“删除有序链表中重复的元素-I”类似,不同点就是链表的元素是有序的,因此可以利用该条件,通过比较相邻元素是否相同从而判断是否有重复元素(因为元素有序,所以重复元素只能出现在相邻元素)从而省去哈希表的使用,从而将空间复杂度由O(n)降为O(1)。
思路:利用三指针:pre、left与right,left与right用于判断pre之后(不包括pre)的[left,right]闭区间范围内是否有重复元素。如果有,则将[left,right]内的元素删去,并且将left移动到right+1位置处,right从left+1开始向后移动。
难点:当删除[left,right]这个区间之后,最新的left与right的val值可能也会相同,因此不能在每次删除[left,right]区时就将pre.next指向最新的left并且移动pre为pre.next,将pre向后移动之后,此时就会遗失之前的pre了。因此更改pre.next的指向并且将pre向后移动是有条件的:当left.val != right.val时,才能将pre.next指向left,并且移动pre。
#三指针##双指针##链表#