关于链表的算法

链表是什么

  1. 数组是一连串同类型元素在连续内存地址存储的一种数据结构,而链表是不连续性的,并且数据类型也不一定一样的数据结构,比如下图所示
  2. 链表的数据结构分为单向链表和双向链表,链表中每个元素存储的位置被称为节点,在单向链表的节点中,每个节点肯定有两个属性,一个是下一级节点地址信息,一般用next存储。另一个是存储节点的元素信息,一般用val存储。在双向链表中的每个节点中会多一个上级节点地址信息,一般用pre(previous)存储。如下图所示
  3. 代码创建节点的方法
# 使用单向链表举例
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
  1. 代码创建链表的方法
class Solution:
    def __init__(self, val):
        self.val = val
        self.next = ListNode()
    # 添加节点
    def add_element(self, val):
        node = ListNode(val)
        self.next.next = node

时间复杂度

访问:O(N)
搜索:O(N)
插入:O(1)
删除:O(1)

链表算法练习

  1. 203移除链表元素
class Solution:
    def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
        dummy = ListNode(next=head)

        pre = dummy

        while pre.next != None:
            if pre.next.val != val:
                pre = pre.next
            else:
                pre.next = pre.next.next
        return dummy.next

dummy是使用节点创建类创建的一个虚拟的节点,用来指向head这个链表第一个元素的内存地址。这样做可以在返回结果的时候直接使用dummy.next进行返回。如果返回的时候没使用dummy.next这个数据,而直接返回的head。那么当head是[7,7,7,7]这种类型的链表时,则会返回[7,7,7,7],而不是[]。这是因为代码中只有pre.next = pre.next.next生效了,变量pre.next的指向一直变化,也就是dummy.next的指向一直变化,而head没用变化造成的。pre = pre.next这一句代码是让pre重新指向到下一个节点。

  1. 206反转链表
    我这里有两种思路,第一种是使用双指针去做,第二种是把head节点的作为标识,而head.next作为需要被移动的元素,直到head.next为None
    • 双指针
# 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: ListNode) -> ListNode:
        pre = None
        cur = head
        while cur:
            nextNode = cur.next
            cur.next = pre
            pre = cur
            cur = nextNode
        return pre

使用双指针的做法,其实就是使用额外的变量去记录变更之后的链表和head,如图:

  • head.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]:
        dummpy = ListNode(next=head)
        while head and head.next:
            pre = head.next
            head.next = head.next.next
            pre.next = dummpy.next
            dummpy.next = pre
        return dummpy.next

以head作为参照物,移动head.next的方法,如图所示

posted @ 2022-08-06 21:56  影梦无痕  阅读(22)  评论(0)    收藏  举报