Given the
head
of a linked list, remove thenth
node from the end of the list and return its head.Example 1:
解题思路:
题目也是希望只traverse一遍,所以也是要用到双指针。一个是当下跑的,一个是当下-n的,就是要移除的点前一个点。
先让curr领跑n个点。然后再curr和prev一起跑,等到curr跑到最后一个点之后,让prev.next = prev.next.next.就删掉了prev后的那个点。
我自己也重写了一遍:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
curr = prev = head
for _ in range(n):
curr = curr.next
if not curr:
return head.next
while curr.next:
curr = curr.next
prev = prev.next
prev.next = prev.next.next
return head
runtime:
#206 Reverse Linked List
Given the
head
of a singly linked list, reverse the list, and return the reversed list.
解题思路:
如果只traverse一遍的话,那么每经过一个店都要都点进行操作。摘下来作为一个新的linked list,然后新掉下来的点都放在新linked list的队头。新旧linked list都要有指针带着,掉下来的点也要有指针指向。所以一共要三个指针。
分别是prev,curr,nxt。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
prev = None
curr = head
while curr:
nxt = curr.next
curr.next = prev
prev = curr
curr = nxt
return prev
runtime:
16ms的没差:
#203 Remove Linked List Elements
Given the
head
of a linked list and an integerval
, remove all the nodes of the linked list that hasNode.val == val
, and return the new head.
解题思路:
当node的val与目标值相同,则去掉当前的点,令prev.next = curr.next。
关键是这个prev的值是否为None,换句话说就是curr这个点万一是第一个点怎么办,这个时候prev就为None,接不上下一个点。
所以安一个假头。sentinel = ListNode(0)
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
sentinel = ListNode(0)
sentinel.next = head
prev, curr = sentinel, head
while curr:
if curr.val == val:
prev.next = curr.next
else:
prev = curr
curr = curr.next
return sentinel.next
最后再返回sentinel.next就等于默认弃掉临时加的假头。
不加假头也行,forum里zayne-siew给的思路是:
分情况讨论,比如第一个就是要去掉的点的话,那么prev一开始是None,就不移动,只移动curr给curr.next。然后head改为head.next就好。如果prev已经有值,那么就是prev.next=curr.next。最后返回head。
class Solution:
def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
prev, curr = None, head
while curr:
if curr.val == val: # cases 1-3
if prev: # cases 1-2
prev.next = curr.next
else: # case 3
head = curr.next
curr = curr.next # for all cases
else: # case 4
prev, curr = curr, curr.next
return head