刷题Day(3)|代码随想录

195 阅读3分钟

本系列文章是我刷代码随想录过程中的笔记。代码地址:leetcode

今天是我刷“代码随想录”的第三天

今日内容

  1. 链表基础
  2. 移除链表元素
  3. 设计链表
  4. 反转链表

链表基础

链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向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)

总结

这些题目都是些基础题目,但我也发现了我在链表上面的不足之处,还是需要多加练习。