Leetcode 203: 移除链表元素
讲解前:
这道题我之前其实就做过,算是一道非常基础的链表题目,在链表中我们明白每一个元素的access其实都需要上一个node来寻找,因为只有node.next才能获取到他,所以删除一个元素最简单的方法就是让其上一个node的next指针跳过他直接指向下下个元素也就是 1->2->3 删除2以后,1的next就应该直接指向3,也就是1->3
class Solution:
def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
res = ListNode(0, head)
prev = res
current = head
while current:
if current.val == val:
prev.next = current.next
current = current.next
else:
prev = prev.next
current = current.next
return res.next
我这里的解法就是利用了一个虚拟的头节点来让其的next指向真正的head,这样以来,哪怕需要删除的节点是头节点,我们也能运用一样的方法了,current node是用来遍历整个链表的所以循环的条件是while current,然后呢prev用来帮助我们have access to the node before current,这样我们才能通过改变prev.next 来删除current node,于是我们让prev初始化为我们创建的指向head的虚拟节点然后让current指向head,在遍历中,每当我们发现current node的值需要被删除,我们就让prev.next指向current.next这里就不需要更新prev了,然后无论是否需要被删除,每次我们都更新current = current.next
讲解后:
看完了卡哥的讲解后发现他不管是不用dummy node的方法还是用的方法,他都只新建了一个current node,然后每一次比较数值的时候检查 curr.next. 然后删除的操作是curr.next = curr.next.next 这个方法其实会让我有些晕,因为while 循环的定义会模糊,检查的是while curr.next != null 所以总让人有种没有彻底遍历到最后一个元素的感觉,但其实这里的curr扮演的角色是我的code中prev扮演的角色
Leetcode 707: 设计链表
讲解前:
这道题其实就是需要我们自己写一个linked list的类,类似的情况在学校的数据结构算法课中都有涉及到,不过为了第一次先成功尝试以及自己完成,我决定先用写单项链表的类试一下
虽然经历了一些debug但是最终还是成功的写出来了,我认为这道题其实并不难,没有什么需要特别注意的算法,在get 和 addatindex中需要先遍历到index然后再执行一个简单的操作就好了
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class MyLinkedList:
def __init__(self):
self.dummy_head = ListNode()
self.size = 0
def get(self, index: int) -> int:
if self.size <= index:
return -1
current = self.dummy_head.next
for _ in range(index):
current = current.next
return current.val
def addAtHead(self, val: int) -> None:
new_node = ListNode(val, self.dummy_head.next)
self.dummy_head.next = new_node
self.size = self.size + 1
def addAtTail(self, val: int) -> None:
current = self.dummy_head
while current.next:
current = current.next
current.next = ListNode(val, None)
self.size = self.size + 1
def addAtIndex(self, index: int, val: int) -> None:
if index > self.size:
return
new_node = ListNode(val, None)
current = self.dummy_head
for _ in range(index):
current = current.next
temp = current.next
current.next = new_node
new_node.next = temp
self.size = self.size + 1
def deleteAtIndex(self, index: int) -> None:
if index >= self.size:
return
current = self.dummy_head
for _ in range(index):
current = current.next
current.next = current.next.next
self.size = self.size - 1
讲解后:
卡哥的思路和我的一样只是在他的讲解中他基本都用了while loop来做,但是我都用了for loop,不过有一个地方我发现我做的时候莫名其妙的复杂化了就是add at index的操作中,我莫名其妙的用了一个temp node,但压根没必要,当我们找到要加的index的前一个node之后直接这样加就可以了
def addAtIndex(self, index: int, val: int) -> None:
if index > self.size:
return
new_node = ListNode(val, None)
current = self.dummy_head
for _ in range(index):
current = current.next
new_node.next = current.next
current.next = new_node
self.size = self.size + 1
Leetcode 206:翻转链表
讲解前:
我记得我之前也做过这道题,我的记忆中需要用到一个temp node去记录什么然后好像又是要从链表的后面往前遍历之类的,我打算一定要自己写出来不看讲解
这道题我还是成功的使用了双指针的解法做了出来,可能是前两道题都利用了dummy node的关系,我在这道题中还是不假思索的写了一个dummy node, 这是我一开始的写法
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
if not head:
return None
dummy = ListNode(None, head)
current = head
prev = dummy
while current:
temp = current.next
current.next = prev
prev = current
current = temp
return prev
我反复debug了很多遍才发现我这样写有一个非常大的问题就是dummy node的next指向head这一点我从来没有变过,也就是说我们翻转完了整个链表最后返回的时候,找回到一开始的旧的head时,他指向的其实是dummy node,我以为dummy的值是None所以这样刚好,但是我忘记了dummy node的next又重新指回了head,这就产生了一个自循环的链表(环形链表),所以我们return的结果永远遍历不完,哪怕我把dummynode的next改成None也不行,因为最后返回的值中最后会多一个null,后来我发现其实这里根本没必要有dummy node,prev一开始就直接设置成null就可以了,然后这是更新过的正确的代码
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
current = head
prev = None
while current:
temp = current.next
current.next = prev
prev = current
current = temp
return prev
讲解后:
看了卡哥的讲解之后对于双指针的解法每个指针的用处还有循环中每一行代码的作用有了更深的理解,然后还按照卡哥说的通过双指针的思路写出了递归的解法
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
return self.reverse(None, head)
def reverse(self, prev, current):
if not current:
return prev
else:
temp = current.next
current.next = prev
return self.reverse(current, temp)