本系列文章是我刷代码随想录过程中的笔记。代码地址:leetcode
今天是我刷“代码随想录”的第三天
今日内容
- 链表基础
- 移除链表元素
- 设计链表
- 反转链表
链表基础
链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。
链表的入口节点称为链表的头结点也就是head。
链表在内存中的地址是不连续的。
分类
- 单链表
- 双链表
- 循环链表
方法
- 删除
- 添加
leetcode 203. 移除链表元素
这是一道简单题。需要注意的是循环条件。只有节点值不等于目标值的时候才能跳转到下一节点。如果不加这个条件,两个连续目标值可能只删除一个。
class Solution:
def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
root = ListNode(-1)
root.next = head
node = root
while node and node.next:
if node.next.val == val:
node.next = node.next.next
else:
node = node.next
return root.next
leetcode 707. 设计链表
这是一道综合题,考察了链表的增删改查。
对于查找来说,根据查找的索引进行循环就好
对于增加来说,因为有增加头节点、尾节点和中间节点三种方式,需要依次实现。
对于删除来说,根据索引进行循环查找,找到后删除就好
代码如下
class MyLinkedList(object):
def __init__(self):
self.head = Node()
self.size = 0 # 设置一个链表长度的属性,便于后续操作,注意每次增和删的时候都要更新
def get(self, index):
if index < 0 or index >= self.size:
return -1
cur = self.head.next
while (index):
cur = cur.next
index -= 1
return cur.val
def addAtHead(self, val):
new_node = Node(val)
new_node.next = self.head.next
self.head.next = new_node
self.size += 1
def addAtTail(self, val):
new_node = Node(val)
cur = self.head
while (cur.next):
cur = cur.next
cur.next = new_node
self.size += 1
def addAtIndex(self, index, val):
if index < 0:
self.addAtHead(val)
return
elif index == self.size:
self.addAtTail(val)
return
elif index > self.size:
return
node = Node(val)
pre = self.head
while (index):
pre = pre.next
index -= 1
node.next = pre.next
pre.next = node
self.size += 1
def deleteAtIndex(self, index):
if index < 0 or index >= self.size:
return
pre = self.head
while (index):
pre = pre.next
index -= 1
pre.next = pre.next.next
self.size -= 1
leetcode 206. 反转链表
这是一道经典题,主要有双指针法和递归法
双指针
定义两个指针,一个指向当前节点,一个指向前节点。循环结束条件为当前节点为空,即所有节点已经遍历完成。
在循环时,首先保存下一个节点,其次进行节点反转,更新当前节点和前节点。
最后返回前节点。代码如下
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
cur = head
pre = None
while(cur!=None):
temp = cur.next # 保存一下 cur的下一个节点,因为接下来要改变cur->next
cur.next = pre #反转
#更新pre、cur指针
pre = cur
cur = temp
return pre
递归法
递归法重复使用定义的reverse函数进行反转。在函数中,如果当前节点为空,那么直接返回前节点。然后定义临时节点保存当前节点的下一个节点,将当前节点的下一个节点指向前节点。
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
def reverse(pre, cur):
if not cur:
return pre
tmp = cur.next
cur.next = pre
return reverse(cur, tmp)
return reverse(None, head)
总结
这些题目都是些基础题目,但我也发现了我在链表上面的不足之处,还是需要多加练习。