删除链表元素专题
删除特定节点(leetcode 203)
难点:第一次写时没有分类讨论,导致忽略了头节点和尾结点情况
困惑:同一句代码为什么我会弹出None type,老师不会?
我的程序中使用了这段代码
while p.next: if p.next.val==p.val: p.next=p.next.next p=p.next 首先逻辑上这段代码是错误的,因为它直接跳过了一个比较,加入3个字母重复,它就会出现问题。其次,如果最后一个节点为虚拟结点,则p会直接指向None,此时p为None Type结构,会在下一次while时出现问题(我的理解)。
法一:直接
def removeElements(self, head, val):
while head and head.val==val:
head=head.next
if head is None:
return head
node=head
while node.next:
if node.next.val==val:
node.next=node.next.next
else:
node=node.next
return head
法二:虚拟节点法
将虚拟结点放在头节点前面,好处是不用分类讨论,一个非常值得借鉴的方法。
def removeElements(self, head, val):
prehead=ListNode(-1)
prehead.next=head
node=prehead
while node.next:
if node.next.val == val:
node.next = node.next.next
else:
node = node.next
return prehead.next
删除链表的倒数第N个结点(19)
难点:不知道链表长度和尾结点
法一
def removeNthFromEnd(self, head, n):
def getLength(head):
length=0
while head:
length+=1
head=head.next
return length
prehead=ListNode(0,head)
length=getLength(head)
cur=prehead
for i in range(1,length-n+1):
cur=cur.next
cur.next=cur.next.next
return prehead.next
法二 双指针
def removeNthFromEnd(self, head, n):
prehead=ListNode(0,head)
fast=head
slow=prehead
for i in range(n):
fast=fast.next
while fast:
fast=fast.next
slow=slow.next
slow.next=slow.next.next
return prehead.next
补充:一个很卧槽的题目
删除链表中的结点(237)
难点:没有给你前驱结点。
想法:把它与后继结点调换内容,再删除这个后继结点,把不会的转变成会的,创造前驱结点(好牛!)
代码是从leetcode题解上看的,膜拜大佬!
def deleteNode(self, node):
node.val=node.next.val
node.next=node.next.next
拓展:删除链表M个结点之后的N个节点
删除重复元素
重复元素保留一个(83)
def deleteDuplicates(self, head):
if head or head.next :
return head
p=head
while p.next:
if p.next.val==p.val:
p.next=p.next.next
else:
p=p.next
return head
重复元素都不要(82)
难点:只考虑了两个重复然后一次性删除,这样就会导致如果有三个重复【1,1,1,2,3】,删除后会变成【1,2,3】
用循环删掉他们
def deleteDuplicates(self, head):
prehead = ListNode(0, head)
p = prehead
while p.next and p.next.next:
if p.next.val == p.next.next.val:
x = p.next.val
while p.next and p.next.val == x:
p.next = p.next.next
else:
p = p.next
return prehead.next
拓展:从未排序链表中移除元素(1836)