代码随想录算法训练营第三天 | 链表-203,707,206

1,链表的常规操作:

class Node(object):
    """节点类"""
    def __init__(self, elem):
        # _elem 存放数据元素
        self.elem = elem
        # _next是下一个节点的标识
        self.next = None

# node = Node(100)

class SingleLinkList(object):
    """单链表类"""
    def __init__(self, node=None):
        self.__head = node  # __代表私有变量

    def is_empty(self):
        """链表是否为空"""
        return self.__head == None

    def length(self):
        """返回链表的长度"""
        # cur 游标,用来移动遍历节点
        cur = self.__head
        # count 记录数量
        count = 0
        while cur != None:
            count += 1
            cur = cur.next
        return count

    def travel(self):
        """遍历整个链表"""
        cur = self.__head
        while cur != None:
            print(cur.elem, end=" ")  # 以空格分隔,默认是换行
            cur = cur.next
        print("")  # 换行

    def add(self, item):
        """链表头部添加元素,头插法"""
        node = Node(item)
        node.next = self.__head
        self.__head = node
        # 特殊情况:原有node为空,以上语句满足该情况

    def append(self, item):
        """链表尾部添加元素,尾插法"""
        node = Node(item)
        if self.is_empty():
            self.__head = node   # 链表为空的情况
        else:                   # 链表不为空的情况
            cur = self.__head
            while cur.next != None:
                 cur = cur.next
            cur.next = node

    def insert(self, pos, item):
        """指定位置添加元素
        :param  pos 从0开始
        insert(2, 100)
        """
        if pos < 0:  # 等同于0 的位置插入,头插法
            self.add(item)
        elif pos > self.length() - 1:
            self.append(item)
        else:
            node = Node(item)
            pre = self.__head
            count = 0
            while count < (pos - 1):
                count += 1
                pre = pre.next
                # 当循环退出后,pre指向pos-1位置
            node.next = pre.next
            pre.next = node  # 以上两行顺序不能变换,不然会丢掉插入数据后面的元素

    # def remove(self, item):
    #     """删除节点方法一:2个节点pre和cur"""
    #     cur = self.__head
    #     pre = None   # 两个游标
    #     while cur != None:
    #         if cur.elem == item:
    #             # 先判断此节点是否是头节点,
    #             if cur == self.__head:
    #                 self.__head = cur.next
    #             else:
    #                 pre.next = cur.next
    #             break  # 为什么没有break 会陷入死循环啊
    #         else:
    #             pre = cur
    #             cur = cur.next
        # 特殊情况1:空链表,退出循环,不执行任何操作,以上语句符合
        # 特殊情况2:删除首节点,pre= none,原语句不行,需要考虑
        # 特殊情况3:删除尾结点,以上语句符合
    def remove(self, item):
        """删除节点方法二:只用一个pre节点"""
        
        while self.__head.elem == item:
            self.__head = self.__head.next
        pre = self.__head
        while pre.next != None:
            if pre.next.elem == item:
                pre.next = pre.next.next
            else:
                pre = pre.next

    def search(self, item):
        """查找节点是否存在"""
        cur = self.__head
        while cur != None:
            if cur.elem == item:
                return True
            else:
                cur = cur.next
        return False
    # 空链表的情况,以上语句符合

if __name__ == "__main__":
    ll = SingleLinkList()
    print(ll.is_empty())
    print(ll.length())
    ll.append(1)
    print(ll.is_empty())
    print(ll.length())
    ll.append(2)
    ll.add(8)
    ll.append(3)
    ll.append(4)
    ll.append(5)
    ll.append(6)
    # 8,1,2,3,4,5,6
    ll.insert(-1, 9)  # 9 8 1 23456
    ll.travel()
    ll.insert(3, 100)  # 9 8 1 100 23456
    ll.travel()
    ll.insert(9, 200)  # 9 8 100 1 23456 200
    ll.travel()
    ll.append(100)
    ll.travel()
    ll.remove(100)
    ll.travel()
    # ll.remove(9)
    # ll.travel()

2,移除链表——移除链表中所有值为val的元素

  • 题目链接:203. 移除链表元素 - 力扣(LeetCode)
  • 主要思路:虚拟头节点:因为暴力解法需要把头结点单独考虑,为了同意删除规则,设置虚拟头节点
  • 难点和易错点:
    • 删除节点操作:找到删除元素的前一个节点,pre.next = pre.next.next
    • 需要考虑特殊情况:删除的是头节点

方法一:原链表删除元素:分两种情况删除,头节点和非头节点的删除方式不同

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

方法二:虚拟头节点:统一规则删除

# 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]:
        # 创建虚拟头节点
        dummy_head = ListNode(next = head)
        # 遍历列表并删除值为val的节点
        current = dummy_head
        while current.next:
            if current.next.val == val:
                current.next = current.next.next
            else:
                current = current.next
        
        return dummy_head.next

 3,设计链表——同1,常规操作

  • 题目链接:707. 设计链表 - 力扣(LeetCode)
  • 思路:链表的常规操作
  • 难点和易错点:
    • 增加节点操作:2步:顺序不能对调,不然的话会丢失后面的元素
      • node.next = cur.next
      • cur.next = node
class MyLinkedList:
    def __init__(self):
        self.dummy_head = ListNode()
        self.size = 0

    def get(self, index: int) -> int:
        if index < 0 or index >= self.size:
            return -1
        
        current = self.dummy_head.next
        for i in range(index):
            current = current.next
            
        return current.val

    def addAtHead(self, val: int) -> None:
        self.dummy_head.next = ListNode(val, self.dummy_head.next)
        self.size += 1

    def addAtTail(self, val: int) -> None:
        current = self.dummy_head
        while current.next:
            current = current.next
        current.next = ListNode(val)
        self.size += 1

    def addAtIndex(self, index: int, val: int) -> None:
        if index < 0 or index > self.size:
            return
        
        current = self.dummy_head
        for i in range(index):
            current = current.next
        current.next = ListNode(val, current.next)
        self.size += 1

    def deleteAtIndex(self, index: int) -> None:
        if index < 0 or index >= self.size:
            return
        
        current = self.dummy_head
        for i in range(index):
            current = current.next
        current.next = current.next.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)

 4,反转链表——递归的方法还不会

  • 题目链接:206. 反转链表 - 力扣(LeetCode)
  • 思路:方法一:双指针;方法二:递归( 目前还不会)
  • 难点和易错点:更新指针的顺序不能反了: pre = cur;cur = temp
# 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 = head
        pre = None
        while cur != None:
            temp = cur.next  # 1,保存原来cur的下一个元素
            cur.next = pre  # 2,翻转
            pre = cur  # 3,往下移动,更新pre和cur指针
            cur = temp  
            
        return pre

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值