707. 设计链表

707. 设计链表

单链表设计

题中已经给了要实现的方法和每个方法的具体功能

  1. 设计时创建一个虚拟节点self.dummy指向头节点,会减少边界问题
  2. 题目中也没有求给链表设置头节点、尾节点,所以整个程序中都不设置头节点、尾节点,否则每次增删都要考虑头尾节点是否发生变化,会增加很多代码
  3. 由于addAtIndex、deleteAtIndex方法实现时要判断传入的index是否有效,所以实例初始化时加个self.size 会让这两个方法实现起来更方便
  4. 额外加个traverse方法,打印遍历链表,方便调试
  5. 先实现addAtHead、addAtTail,再实现get,最后实现addAtIndex、deleteAtIndex
class Node:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next


class MyLinkedList:

    def __init__(self):
        """只需要设置这两个必须字段,有了self.dummy每次遍历从虚拟节点开始遍历,不需要头节点,因为虚拟节点指向的就是头节点
        设置的变量属性越少,代码问题就越少"""
        self.dummy = Node() # 设置一个虚拟头节点
        self.size = 0  # 记录当前节点数量,因为addAtIndex、deleteAtIndex都需要判断当前节点数量

    def get(self, index: int) -> int:
        """获取链表中下标为 index 的节点的值。如果下标无效,则返回 -1 。"""
        # 判断下标是否有效
        if index >= self.size:
            return -1
        # [1,2,3] index=2
        cur = self.dummy
        for _ in range(index+1):
            cur = cur.next
        return cur.val

    def addAtHead(self, val: int) -> None:
        """将一个值为 val 的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。"""
        # 创建一个node指向原本self.dummy的下一个节点,然后让self.dummy指向该节点
        new_node = Node(val, self.dummy.next)
        self.dummy.next = new_node
        self.size += 1

    def addAtTail(self, val: int) -> None:
        """ 将一个值为 val 的节点追加到链表中作为链表的最后一个元素。"""
        # 遍历链表 到最后一个节点,设置next为new_node
        new_node = Node(val)
        # 遍历的时候弄个临时指针,如果用self.dummy循环,那就会导致self.dummy最终指向最后一个节点,而self.dummy应该是不变的
        cur = self.dummy
        while cur.next:
            cur = cur.next
        cur.next = new_node
        self.size += 1

    def addAtIndex(self, index: int, val: int) -> None:
        """将一个值为 val 的节点插入到链表中下标为 index 的节点之前。
        如果 index 等于链表的长度,那么该节点会被追加到链表的末尾。
        如果 index 比长度更大,该节点将 不会插入 到链表中。"""
        # 先判断index和链表长度的关系
        if index > self.size:
            return
        elif index == self.size:
            self.addAtTail(val)
            return
        # 当index < size,遍历链表,将一个值为 val 的节点插入到链表中下标为 index 的节点之前
        # 需要找到前一个节点pre_node, 新节点next指向pre_node.next,pre_node.next指向新节点
        pre_node = self.dummy
        for _ in range(index):  # [1,2,3] index=2
            pre_node = pre_node.next
        new_node = Node(val, pre_node.next)  # 这里不需要判断pre_node.next是否为空等边界条件,是因为方法最开头就做了长度判断
        pre_node.next = new_node
        self.size += 1


    def deleteAtIndex(self, index: int) -> None:
        """如果下标有效,则删除链表中下标为 index 的节点。"""
        # 先判断下标是否有效
        if index >= self.size:
            return
        # 当index < size,遍历链表,将pre_node的next指向pre_node.next.next
        pre_node = self.dummy
        for _ in range(index):  # [1,2,3] index=0
            pre_node = pre_node.next
        pre_node.next = pre_node.next.next  # 这里不需要判断pre_node.next是否为空,是因为方法最开头就做了长度判断,代码走到这里一定有pre_node.next
        self.size -= 1



    def traverse(self):
        """遍历链表"""
        result = []
        cur = self.dummy
        while cur.next:
            cur = cur.next
            result.append(cur.val)
        print(result)


# Your MyLinkedList object will be instantiated and called as such:
obj = MyLinkedList()
obj.addAtHead(7)
obj.addAtHead(2)
obj.addAtHead(1) # [1 2 7]
obj.traverse()
obj.addAtIndex(3,0) # [1 2 7 0 ]
obj.traverse()
obj.deleteAtIndex(2) # [1 2 0 ]
obj.traverse()
obj.addAtHead(6)  # [6 1 2 0 ]
obj.traverse()
obj.addAtTail(4) # [6 1 2 0 4]
obj.traverse()
obj.addAtHead(4)
obj.addAtIndex(5,0)
obj.addAtHead(6)  # [6 4 6 1 2 0 0 4]
obj.traverse()

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值