LeetCode 203.移除链表元素
题目链接
思路
两种方式删除链表
一:不用虚拟头节点。删除的元素在头节点,直接让head=head.next。删除的元素不在头节点,设置一个移动指针cur指向头节点,开始让cur.next = cur.next.next。(注意两次操作都要先判空,因为不可以操作空指针)
二、用虚拟头节点。设置移动指针cur = dummyhead,同上表述的步骤二(不需要再判断删除元素是否在头节点,代码更简洁)
代码如下:
(不用虚拟头节点的没写出来,但是小趴菜还没找到原因,先贴出来,方便的话欢迎懂的盆友评论指出,救救小趴菜)
# 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]:
#不用虚拟头节点
while (head != None) and (head.val == val):
head = head.next
cur = head
while cur.next != None:
if cur.next.val == val:
cur.next = cur.next.next
else:
cur = cur.next
return head
(带虚拟头节点的在这,这个过了):
class Solution:
def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
#带虚拟头节点
dummyhead = ListNode(next = head)
cur = dummyhead
while cur.next != None:
if cur.next.val == val:
cur.next = cur.next.next
else:
cur = cur.next
return dummyhead.next
反思
不懂是python 的原因还是啥,感觉不用虚拟头指针的思路是对的,但是无法通过。还是用虚拟头指针会方便很多,因为流程是一样的,不用多做一个情况判断
LeetCode 707.设计链表
题目链接
思路
(单链表的)
class Node:
def __init__(self, val=0):
self.val = val
self.next = None
class MyLinkedList:
def __init__(self):
self.head = Node()
self.size = 0
def get(self, index: int) -> int:
cur = self.head.next
if index<0 or index>=self.size:
return -1
else:
while index:
cur = cur.next
index -= 1
return cur.val
def addAtHead(self, val: int) -> None:
newnode = Node(val)
newnode.next = self.head.next
self.head.next = newnode
self.size += 1
def addAtTail(self, val: int) -> None:
newnode = Node(val)
cur = self.head
'''n = self.size
if self.size == 0:
self.head.next = newnode
else:
while n:
cur = next
n -= 1
cur.next = newnode'''
while cur.next:
cur = cur.next
cur.next = newnode
self.size += 1
def addAtIndex(self, index: int, val: int) -> None:
newnode = Node(val)
cur = self.head
if index < 0:
self.addAtHead(val)
return
elif index == self.size:
self.addAtTail(val)
return
elif index > self.size:
return
while index:
cur = cur.next
index -= 1
newnode.next = cur.next
cur.next = newnode
self.size += 1
def deleteAtIndex(self, index: int) -> None:
cur = self.head
if index < 0 or index >= self.size:
return
else:
while index:
cur = cur.next
index -= 1
cur.next = cur.next.next
self.size -= 1
(双链表的)
class Node:
def __init__(self, val=0):
self.val = val
self.next = None
self.prev = None #新增的指向上一个节点
class MyLinkedList:
def __init__(self):
self.head, self.tail = Node(), Node() #增加了一个虚拟尾指针
self.head.next, self.tail.prev = self.tail, self.head
self.size = 0
def _getNode(self, index: int) -> Node:
#如果index大于长度的一半,则从尾巴开始找比较快,反之从头更快
if index >= (self.size // 2):
cur = self.tail.prev
for _ in range(self.size - index - 1):
cur = cur.prev
else:
cur = self.head.next
for _ in range(index):
cur = cur.next
return cur
def get(self, index: int) -> int:
#如果index大于长度的一半,则从尾巴开始找比较快,反之从头更快
if index<0 or index>=self.size:
return -1
else:
cur = self._getNode(index)
return cur.val
def addAtHead(self, val: int) -> None:
newnode = Node(val)
if self.head.next != None:
self.head.next.prev = newnode
newnode.next = self.head.next
newnode.prev = self.head
self.head.next = newnode
self.size += 1
def addAtTail(self, val: int) -> None:
newnode = Node(val)
newnode.prev = self.tail.prev
self.tail.prev.next = newnode
newnode.next = self.tail
self.tail.prev = newnode
self.size += 1
def addAtIndex(self, index: int, val: int) -> None:
newnode = Node(val)
if index < 0:
self.addAtHead(val)
return
elif index == self.size:
self.addAtTail(val)
return
elif index > self.size:
return
a = self._getNode(index)
a.prev.next = newnode
newnode.prev = a.prev
newnode.next = a
a.prev = newnode
self.size += 1
def deleteAtIndex(self, index: int) -> None:
if index < 0 or index >= self.size:
return
else:
a = self._getNode(index)
a.prev.next = a.next
a.next.prev = a.prev
self.size -= 1
# Your MyLinkedList object will be instantiated and called as such:
# obj = MyLinkedList()
# param_1 = obj.get(index)
# obj.addAtHead(val)
# obj.addAtTail(val)
# obj.addAtIndex(index,val)
# obj.deleteAtIndex(index)
反思
对于链表的基本操作:增删查,增分为头插和尾插。双链表比单链表做操作更方便,因为增加了一个向前指的指针(记得双链表要增加一个虚拟尾节点)
LeetCode 206.反转链表
题目链接
思路
暴力方案是找到最后一个节点,一个一个往前,塞进一个新的链表里面,打印新链表
卡哥思路:利用双指针。一个指向当前节点,一个指向前一个节点,让当前节点的next指向前一个节点,直到当前节点为空
# 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]:
cur = head
prev = None
while cur:
temp = cur.next
cur.next = prev
prev = cur
cur = temp
return prev
(更简洁的代码是整理成递归代码,思路还是双指针)
class Solution:
def reverse(self, cur, prev):
if cur == None:
return prev
temp = cur.next
cur.next = prev
return self.reverse(temp, cur)
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
return self.reverse(head, None)
反思
反转链表主要通过双指针思想,改变指针的指向,让原本向后指的指针向前。自己想的时候过于复杂,一个一个节点遍历出来还要建一个新的链表,直接再原链表基础上改变方向即达到需求