输入:1->1->2->3->3->None
输出:2->None
这种题目lintcode里还挺多的,设计多指针,能做出来,但过程中总是有这样的那样的错误,耗费时间 较多,有必要好好总结一下。
1.凡是链表操作的题目,肯定要有个指针要从头到尾便历了,看看每个Node是否满足要求。为了统一处理,我们通常在链表头部加个表头prehead,这样我们即使在删除head的时候,也和其他位置的node是同样处理。
2.链表的优势就在于添加,删除之类的操作。链表做这些操作,必须要知道2个位置,拿删除来说,那就是被删除节点的前一个节点位置和后一个节点位置。这道题是要删除全部有重复的节点,而且这些被删除的节点是连续的,那么我们此时还是需要2个位置,这些节点的前一个节点和后一个节点。
3.便历链表,通常做法是
cursor = head
while(cursor):
{
do something
cursor = cursor.next
}
需要注意的的是while中的判断
如果输入是1->2->3->4->None,while(cursor)会便历完全部的节点。当你的循环中需要用到cur.next的value(不是下面的cursor = cursor.next)时,do sth的时候如果不做附加的判断,会越界。然而while(cursor.next)会忽略掉4。所以,建议在do sth中增加判断。
4.初始时selectednode = prehead ,lastsamenode = head,两个指针分别有不同的功能,selectednode 是用来串珍珠项链的绳子, lastsamenode用来挑选合适的珍珠(标准是第一个不同的节点)selectednode要出现在这个lastsamenode前面。
对于本题,selectednode 后面的需要的操作的是,要么保存它的nextnode,要么跳过他的nextNode(这里是一次跳过全部的重复项)。
def deleteDuplicates(self, head):
# write your code here
prehead = ListNode(None)
prehead.next = head
selectednode = prehead #为了能将重复的节点跳过去,selectednode必须出现在第一次出现的Node的前面,也就是上面第二条中的"前一个节点"
lastsamenode = head #移动到最后一个重复的节点。也就是上面第二条中的"后一个节点",这个名字有点怪,实际上最后成为第一个不同的节点。
while lastsamenode :
target = lastsamenode.val
lastsamenode = lastsamenode.next
if lastsamenode and target == lastsamenode.val:
while lastsamenode and lastsamenode.val == target:
lastsamenode = lastsamenode.next
#跳过原来的selectednode.next
selectednode.next = lastsamenode
else:
#保存selectednode.next
selectednode = selectednode.next
return prehead.next