代码随想录27期|Python|Day3|链表基础|203移除链表元素、707设计链表、206反转链表

链表基础

链表和数组在查询和增删的时候的时间复杂度如下(图源:代码随想录):

关于删除C|C++需要手动free内存,但是Java和Python等会自动回收内存。

Python定义链表如下:

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

203.移除链表元素

思路

原链表删除:需要单独判断需要删除的是不是head,如果是的话需要把当前的head往后移动一个。

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution(object):
    def removeElements(self, head, val):
        """
        :type head: ListNode
        :type val: int
        :rtype: ListNode
        """
        # 原链表删除
        current = head
        while current.next:
            if current.val == val:
                head = current.next
                current = head
            elif current.next.val == val:
                current.next = current.next.next
            else:
                current = current.next
        return current

虚拟头节点(dummy_head):为了解决如果需要删除头节点的情况,不用再写一个if单独判断。方法是定义一个在原来head之前的节点dummy_head,使得dummy_head.next = head,这样以dummy_head作为起点删除任何的节点都是从第二个开始,可以统一成一个while里。

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution(object):
    def removeElements(self, head, val):
        """
        :type head: ListNode
        :type val: int
        :rtype: ListNode
        """
        # 虚拟节点
        dummy_head = ListNode(next = head)
        current = dummy_head  # 从虚拟节点作为起始点开始,所有的删除都是在第二个节点开始,可以统一到一个while里面
        while current.next:  # 用当前节点的下一个是否是None来判断是否是最后一个节点
            if current.next.val == val:
                current.next = current.next.next
            else:
                current = current.next
        return dummy_head.next  # 注意!!返回的是dummy的后一个

707.设计链表(很重要!!涉及链表的全部操作)

思路

单链表+dummy_head

# 定义节点类,需要传入data和next指针
class LinkNode:
    def __init__(self, val = 0, next = None):
        self.val = val
        self.next = next

class MyLinkedList(object):

    def __init__(self):
        self.dummy_head = LinkNode() # 定义一个虚拟节点(实际上是链表的第一个节点)
        self.size = 0  # 用于index合法性判断

    # 获取当前节点的值
    def get(self, index):
        """
        :type index: int
        :rtype: int
        """
        # 合法性判断
        if index < 0 or index >= self.size:
            return -1

        current = self.dummy_head.next  # 当前从头节点开始,for range之后就是停留在目标节点

        for _ in range(index):
            current = current.next

        return current.val

    # 添加头节点
    def addAtHead(self, val):
        """
        :type val: int
        :rtype: None
        """
        self.dummy_head.next = LinkNode(val, self.dummy_head.next)  # 也就是把dummy_head的next指向新的节点,在此之前需要先把原头节点的指针传给新节点的next,不然会丢失!!!!
        self.size += 1


    def addAtTail(self, val):
        """
        :type val: int
        :rtype: None
        """
        current = self.dummy_head  # 从dummy开始for range之后停留在index节点的前一个
        while current.next:
            current = current.next
        current.next = LinkNode(val, None)  # None也可以不加
        self.size += 1


    def addAtIndex(self, index, val):
        """
        :type index: int
        :type val: int
        :rtype: None
        """
        # 合法性检验
        if index < 0 or index > self.size:
            return

        current = self.dummy_head
        for _ in range(index):
            current = current.next
        current.next = LinkNode(val, current.next)  # 和插入头节点类似
        self.size += 1


    def deleteAtIndex(self, index):
        """
        :type index: int
        :rtype: None
        """
        if index < 0 or index >= self.size:
            return 

        current = self.dummy_head

        for _ in range(index):
            current = current.next

        current.next = current.next.next  # 相当于跨过了current.next连接

        self.size -= 1


# Your MyLinkedList object will be instantiated and called as such:
# obj = MyLinkedList()
# param_1 = obj.get(index)
# obj.addAtHead(val)
# obj.addAtTail(val)
# obj.addAtIndex(index,val)
# obj.deleteAtIndex(index)

206.反转链表

思路

图:代码随想录

双指针+循环 

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution(object):
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        #  双指针法
        pre = None  # pre初始化为None,是新链表的末尾
        cur = head  # cur是当前的节点,初始化为head
        while cur:  # 当cur没有走到None的时候
            temp = cur.next  # 首先保存cur的下一个节点,为了下一步移动cur
            cur.next = pre  # 然后把当前cur的指向反转到pre
            
            # 更新pre和cur,注意顺序
            pre = cur
            cur = temp
        return pre

递归

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution(object):
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        return self.reserve(head, None)
        # 递归法
    def reserve(self, cur, pre):
        if cur == None:  # 递归退出条件:当前节点是None
            return pre
        temp = cur.next  # 先保存当前节点的下一个
        cur.next = pre  # 反转指向pre
        return self.reserve(temp, cur)  # 更新

第三天结束🎉

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值