一、题目分析 && 整体思路
如题所述,原题中给定的是一个排序的链表,所以它重复的元素都一定是相邻的;
如果采用遍历的方式,那就可以:
1、把这个链表从头到尾遍历一遍,找到相邻的重复元素节点;
2、再把重复的元素节点删掉,只保留一个元素节点。
二、如何删除重复节点,或者说如何在相同节点中只保留一个
要保证连续多个元素相同的情况下都能适应,我们把这个题分成了两种情况:一种是连续两个元素相同的情况、另一种是连续两个元素以上相同的情况。
1、两个元素相同
当发现当前节点的值与下一个节点的值相同,就把后面的相同节点删除掉,current就继续向下走,如果发现不同,就继续向下移动,current移动到最后就完成了。
2、两个元素以上相同
current发现当前节点值与下一个节点值相同,删除下一节点,也就用cur.next = cur.next.next,current的next指针也就指向了当前节点的下一个的下一个节点。然后再此比较当前节点的值与下一个节点的值是否相同的,结果发现还是相同的,这时候,我们再次执行一遍cur.next = cur.next.next,这时的next节点又向下指向了一个节点。
如果再下一个节点不再相同,则current就可以向下移动节点了。
三、头尾边界条件的处理
首先来看这道题需不需要虚拟头节点?
不需要,因为我们的思路是当遇到两个元素重复的时候,我们去删除掉重复元素后面的元素,保留所有重复元素的第一个,即使第一个元素和第二个元素重复,我们也是去删除第二个元素,也就是说头节点无论在什么情况下都不会被删除的,自然也就不需要虚拟头节点了。
current需要在最后一个节点还是倒数第二个节点就可以完成任务?
current在倒数第二个节点是完全可以的,因为我们可以比较current和current.next这两个值。
当最后两个值不同,我们已经将current和current.next这两个值做了比较,是不需要继续往下移动的;
当最后两个值相同,current在最后倒数第二个节点的位置就可以将最后一个节点删除了,将current.next指向null,因为在链表中,哪个元素的下一个节点指向了null,哪个元素就是最后一个节点,所以,也不需要继续往下移动。
设定current移动到倒数第二个位置的条件是:cur != null && cur.next != null。
Code
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode deleteDuplicates(ListNode head) {
ListNode cur = head;//current的起始位值是真正的头节点(不需要虚拟头节点)
//current的终止条件,也就是需要current在链表中的倒数第二个节点停下
while(cur != null && cur.next != null){
//如果值相同,则删除掉下一个节点
if(cur.val == cur.next.val){
cur.next = cur.next.next;
}else{
//如果值不相同,就将current下移
cur = cur.next;
}
}
return head;
}
}