Day 3 | 203.移除链表元素、 707.设计链表、206.反转链表

91 阅读2分钟

链表理论基础

链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。

image.png

单链表:

上文所说即单链表

双链表:

每个节点有两个指针,一个指向前节点,一个指向后节点,所以双链表既可以向后查询也可以向前查询

image.png

循环链表:

首尾相连的链表即为循环链表

image.png

链表的定义

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

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…

思路

使用dummy虚拟节点,删除对应节点,最后返回dummy.next

代码

class Solution:
    def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
        dummy = ListNode(next=head)
        cur = dummy
        while cur.next:
            if cur.next.val == val:
                cur.next = cur.next.next
            else:
                cur = cur.next
        return dummy.next

707.设计链表

题目描述

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

示例

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

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

思路

设立虚拟头结点再进行操作

代码

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


class MyLinkedList:

    def __init__(self):
        self.head = Node(0) #虚拟头结点
        self.count_ = 0     #添加的节点数

    def get(self, index: int) -> int:
        if 0 <= index < self.count_:
            cur = self.head
            for _ in range(index + 1):
                cur = cur.next
            return cur.val
        else:
            return -1


    def addAtHead(self, val: int) -> None:
        self.addAtIndex(0, val)

    def addAtTail(self, val: int) -> None:
        self.addAtIndex(self.count_, val)

    def addAtIndex(self, index: int, val: int) -> None:
        if index < 0:
            index = 0
        elif index > self.count_:
            return
        
        self.count_ += 1
        add_node = Node(val)
        pre_node, cur_node = None, self.head
        
        for _ in range(index + 1):
            pre_node, cur_node = cur_node, cur_node.next
        else:
            pre_node.next, add_node.next = add_node, cur_node 

    def deleteAtIndex(self, index: int) -> None:
        if 0 <= index < self.count_:
            self.count_ -= 1
            pre_node, cur_node = None, self.head 
            for _ in range(index + 1):
                pre_node, cur_node = cur_node, cur_node.next
            else:
                pre_node.next, cur_node.next = cur_node.next, None


206.反转链表

题目描述

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例

image.png

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

思路

首先定义一个cur指针,指向头结点,再定义一个pre指针,初始化为null。 先要把 cur->next 节点用tmp指针保存一下,也就是保存一下这个节点。

将cur->next 指向pre ,此时已经反转了第一个节点了。 继续移动pre和cur指针。

最后,cur 指针已经指向了null,循环结束,链表也反转完毕了。return pre即可,此时pre指向了新的头结点。

代码

# 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, pre = head, None
        while cur:
            tmp = cur.next
            cur.next = pre
            pre = cur
            cur = tmp
        return pre

总结

重新复习了一遍链表,要学会灵活使用虚拟头结点,另外设计链表的每个操作都要掌握,注意细节。