203.移除链表元素 , 707.设计链表, 206.反转链表

6. LeetCode 203. 移除链表元素

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点

示例 1:

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

示例 2:

输入:head = [], val = 1
输出:[]

示例 3:

输入:head = [7,7,7,7], val = 7
输出:[]

提示:

  • 列表中的节点数目在范围 [0, 104]
  • 1 <= Node.val <= 50
  • 0 <= val <= 50

解法:

  • 构造头结点,因为每个链表节点都是一个对象,浅拷贝的占用同一个内存地址。

    class ListNode:
        def __init__(self, val):
            self.val = val
            self.next = None
    
    def remove_elements(head: Optional[ListNode], val: int) -> Optional[ListNode]:
        dummy_node = ListNode(0)
        dummy_node.next = head
        cur = dummy_node
        while cur.next:
            if cur.next.val == val:
                cur.next = cur.next.next
            else:
                cur = cur.next
        return dummy_node.next
    

测试用例:

  • def base_test_case() -> ListNode:
        node1 = ListNode(1)
        node2 = ListNode(2)
        node3 = ListNode(3)
        node4 = ListNode(4)
        node5 = ListNode(5)
        node6 = ListNode(6)
        node1.next = node2
        node2.next = node3
        node3.next = node4
        node4.next = node5
        node5.next = node6
        return node1
    
    if __name__ == '__main__':
        test_object = remove_elements(base_test_case(), 6)
        print(test_object)
    
7. LeetCode 707. 设计链表

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

在链表类中实现这些功能:

  • get(index):获取链表中第 index 个节点的值。如果索引无效,则返回 -1
  • addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
  • addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
  • addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index大于链表长度,则不会插入节点。如果 index 小于 0,则在头部插入节点。
  • deleteAtIndex(index):如果索引 index有效,则删除链表中的第 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

提示:

  • 0 <= index, val <= 1000

  • 请不要使用内置的 LinkedList 库。

  • get, addAtHead, addAtTail, addAtIndexdeleteAtIndex 的操作次数不超过 2000

  • class MyLinkedList:
        def __init__(self):
            pass
    
        def get(self, index: int) -> int:
    		pass
    
        def addAtHead(self, val: int) -> None:
            pass
        
        def addAtTail(self, val: int) -> None:
            pass
        
        def addAtIndex(self, index: int, val: int) -> None:
            pass
    
        def deleteAtIndex(self, index: int) -> None:
            pass
    

解法:

    1. 对于初始化属性,需要考虑链表的节点个数
    2. 对于头部和尾部添加:都可以采用插入的方法(头部和尾部的索引已知)
    3. 添加和删除链表节点的时候,要对链表节点个数进行相应的加减
    class MyLinkedList:
        """
        设计链表的实现。
        """
        def __init__(self):
            self.dummy_node = ListNode(0)
            self.count = 0
    
        def get(self, index: int) -> int:
            """get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。"""
            if index >= self.count or index < 0:
                return -1
            else:
                cur = self.dummy_node
                for _ in range(index + 1):
                    cur = cur.next
                return cur.val
    
        def addAtHead(self, val: int) -> None:
            """在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。"""
            self.addAtIndex(0, val)
    
        def addAtTail(self, val: int) -> None:
            """值为 val 的节点追加到链表的最后一个元素。"""
            self.addAtIndex(self.count, val)
            
        def addAtIndex(self, index: int, val: int) -> None:
            """
            在链表中的第 index 个节点之前添加值为 val 的节点。
            如果 index 等于链表的长度,则该节点将附加到链表的末尾。
            如果 index 大于链表长度,则不会插入节点。如果 index 小于 0,则在头部插入节点。
            """
            if index < 0:
                index = 0
            elif index > self.count:
                return
    
            self.count += 1
            add_node = ListNode(val)
            pre = None
            cur = self.dummy_node
            for _ in range(index + 1):
                pre = cur
                cur = cur.next
            pre.next = add_node
            add_node.next = cur
            
        def deleteAtIndex(self, index: int) -> None:
            """如果索引 index 有效,则删除链表中的第 index 个节点。"""
            if 0 <= index < self.count:
                self.count -= 1
                pre = None
                cur = self.dummy_node
    
                for _ in range(index + 1):
                    pre = cur
                    cur = cur.next
                pre.next = cur.next
                cur.next = None
    

测试用例:

 my_linked_list = MyLinkedList()
 my_linked_list.dummy_node.next = base_test_case()
 my_linked_list.count = 6
 result_val = my_linked_list.get(6)
 print(result_val)

 my_linked_list.addAtHead(4)
 my_linked_list.addAtTail(10)
 result_add = my_linked_list.dummy_node.next
 print(result_add)

 my_linked_list.deleteAtIndex(5)
 result_del = my_linked_list.dummy_node.next
 print(result_del)
8. 206. 反转链表

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

示例 1:
在这里插入图片描述

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

示例 2:

输入:head = [1,2]
输出:[2,1]

示例3:

输入:head = []
输出:[]

提示:

  • 链表中节点的数目范围是 [0, 5000]
  • -5000 <= Node.val <= 5000

解法:

  • 双指针法

    def reverseList(head: Optional[ListNode]) -> Optional[ListNode]:
        pre = None  # 左指针
        cur = head  # 右指针
        while cur:  
            tmp = cur.next  # 第一个节点的next赋值为tmp(后面的一串节点)
            cur.next = pre  # pre赋值为第一个节点的next(此时pre为None,反转后的尾节点的next为None)
            pre = cur  # 移动右指针
            cur = tmp  # 移动左指针
        return pre
    
  • 测试用例:

    node1 = ListNode(1)
    node2 = ListNode(2)
    node3 = ListNode(3)
    node4 = ListNode(4)
    node5 = ListNode(5)
    node6 = ListNode(6)
    node1.next = node2
    node2.next = node3
    node3.next = node4
    node4.next = node5
    node5.next = node6
    
    reverse_list(node1)
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值