算法记录 | Day3链表基础

98 阅读2分钟

算法记录 | Day3链表基础

LeetCode 203-移除链表元素

题目描述:给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点

输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]

题目链接:leetcode.cn/problems/re…

解题思路
  • 该题就是最简单的移除链表。

双指针法

# 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]:  
        # 虚拟头结点
        pre_node = ListNode(next=head)
        # print(pre_node)
        node = pre_node
        while node.next:
            if node.next.val == val:
                node.next = node.next.next
            else:
                node = node.next
        return pre_node.next
重点
  • 虚拟头节点的设置
总结

基础题,第一次做可能不知道节点的写法。


LeetCode 707-设计链表

设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。

题目链接:leetcode.cn/problems/de…

MyLinkedList linkedList = new MyLinkedList();
linkedList.addAtHead(1);
linkedList.addAtTail(3);
linkedList.addAtIndex(1,2);   //链表变为1-> 2-> 3
linkedList.get(1);            //返回2
linkedList.deleteAtIndex(1);  //现在链表是1-> 3
linkedList.get(1);            //返回3
解题思路
  • 链表的基本操作

解法

class Node:  
    def __init__(self, val, next=None):
        self.val = val
        self.next = next

class MyLinkedList:

    def __init__(self):
        # 链表在操作的时候最好设置虚拟头节点
        self.head = Node(0)
        self.length = 0
    
    def get(self, index: int) -> int:
        # 注意条件, 如果索引无效
        if self.length >=0 and index < self.length:
            p = self.head
            for i in range(index+1):
                p = p.next       
            return p.val
        else:
            return -1

    def addAtHead(self, val: int) -> None:
        # 在链表的第一个元素之前添加值为val的节点
        node = Node(val)
        node.next = self.head.next
        self.head.next = node
        # 注意,节点数要+1
        self.length += 1

    def addAtTail(self, val: int) -> None:
        # 加到尾部
        tail_node = Node(val)
        p = self.head
        while p.next:
            p = p.next
        p.next = tail_node
        self.length += 1

    def addAtIndex(self, index: int, val: int) -> None:
        if index <= 0:
            self.addAtHead(val)
            return
        if index == self.length:
            self.addAtTail(val)
            return
        if index > self.length:
            return
        # 第index节点之前添加
        node = Node(val)
        p = self.head
        for i in range(index):
            p = p.next
        node.next = p.next
        p.next = node
        ## 忘记长度+1
        self.length += 1

    def deleteAtIndex(self, index: int) -> None:
        if index<0 or index >= self.length:
            return
        p = self.head
        for i in range(index):
            p = p.next
        p.next = p.next.next
        ### 忘记了长度-1...
        self.length -= 1

注意:

难点
  • 虚拟头节点如何设置,注意__init__ 下面的写法
  • 细节上,总是忘记长度+1 -1的操作
  • 边界细节处理不好容易空指针
总结

这道题本身就是一些基础操作,关键难点在于处理细节上,一不小心就会出现指针指到空的位置。


LeetCode 206-反转链表

题目描述:给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

题目链接:leetcode.cn/problems/re…

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
解题思路
  • 循环反转:思考反转的过程只需要改变指针的方向即可
class Solution:
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        cur = head
        pre = None
        while cur:
            temp = cur.next
            cur.next = pre
            pre = cur
            cur = temp
        return pre 
难点

如何思考反转

总结

收获:重新复习了一遍链表的结构,细节方面还得更加仔细注意,很容易出错。