Leetcode刷题第三天 | 203,707,206

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

Leetcode 203

题目:

给你一个链表的头节点 head 和一个整数val ,请你删除链表中所有满足Node.val == val的节点,并返回新的头节点
示例 1:
例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
输出:[]

实现方法:

  1. 不带头指针的方法
  2. 带头指针的方法

代码实现:

链表结构定义:
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]:
        # 没有头结点版本
        # 如果链表的元素都是一样的,那么连续删除
        while head != None and head.val == val: # 为什么加个while 假如链表的元素都是一样的
            head = head.next
        
        cur = head
        while cur != None and cur.next != None:     
        # 这里的cur != None 统计的是当链表仅有一个元素的时候,防止cur.next 是NoneType
            # cur != None:是因为接下来要操作cur.next
            # cur.next != None: 是因为接下来要取出来cur.next的val
            if cur.next.val == val:
                cur.next = cur.next.next
            else: 
                cur = cur.next
        return head
带头指针实现:
class Solution:
    def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
        # 有头结点版本
        # 首先要创建虚拟头结点
        dummy_head = ListNode(next=head)
        
        # 不能直接循环虚拟头结点,而是定义当前循环节点
        current = dummy_head
        while current.next != None:
            if current.next.val == val:
                current.next = current.next.next
            else:
                current = current.next
        return dummy_head.next # 不能直接返回头结点,可能得情况是当前头结点被删除了
复杂度:

时间复杂度: O ( n ) O(n) O(n),因为要循环遍历整个列表
空间复杂度: O ( 1 ) O(1) O(1)

Leetcode 707

题目

你可以选择使用单链表或者双链表,设计并实现自己的链表。
单链表中的节点应该具备两个属性:val 和 next 。val 是当前节点的值,next 是指向下一个节点的指针/引用。
如果是双向链表,则还需要属性 prev 以指示链表中的上一个节点。假设链表中的所有节点下标从 0 开始。
实现 MyLinkedList 类:
MyLinkedList() 初始化 MyLinkedList 对象。
int get(int index) 获取链表中下标为 index 的节点的值。如果下标无效,则返回 -1 。
void addAtHead(int val) 将一个值为 val 的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。
void addAtTail(int val) 将一个值为 val 的节点追加到链表中作为链表的最后一个元素。
void addAtIndex(int index, int val) 将一个值为 val 的节点插入到链表中下标为 index 的节点之前。如果 index 等于链表的长度,那么该节点会被追加到链表的末尾。如果 index 比长度更大,该节点将 不会插入 到链表中。
void deleteAtIndex(int index) 如果下标有效,则删除链表中下标为 index 的节点。
示例:
输入
[“MyLinkedList”, “addAtHead”, “addAtTail”, “addAtIndex”, “get”, “deleteAtIndex”, “get”]
[[], [1], [3], [1, 2], [1], [1], [1]]
输出
[null, null, null, null, 2, null, 3]
解释
MyLinkedList myLinkedList = new MyLinkedList();
myLinkedList.addAtHead(1);
myLinkedList.addAtTail(3);
myLinkedList.addAtIndex(1, 2); // 链表变为 1->2->3
myLinkedList.get(1); // 返回 2
myLinkedList.deleteAtIndex(1); // 现在,链表变为 1->3
myLinkedList.get(1); // 返回 3

单链表定义
class ListNode:
    def __init__(self, val=0, next=None) -> None:
        self.val = val
        self.next = next
代码实现(这里仅列出但列表法)
class MyLinkedList:
    def __init__(self) -> None:
        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=val)
        self.size += 1

    def addAtIndex(self, index: int, val: int) -> None:
        if index < 0  or index > self.size: # 这里为什么是大于,如果是等于index,就在最后一个位置插入钙元素即可
            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

myLinkedList = MyLinkedList()
myLinkedList.addAtHead(1)
myLinkedList.addAtTail(3)
myLinkedList.addAtIndex(1, 2)

myLinkedList.get(1)            # 返回 2
myLinkedList.deleteAtIndex(1)   # 现在,链表变为 1->3
myLinkedList.get(1)

Leetcode 206

题目

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
示例1:
示例1
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

示例2:
示例2
输入:head = [1,2]
输出:[2,1]
示例 3:
输入:head = []
输出:[]

实现方法:

  1. 双指针法
  2. 递归法

代码实现:

链表结构:
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
双指针法:
class Solution:
    def reverseList(self, head):
        # 利用双指针法  
        current = head
        pre = None
        while current:
            temp = current.next # 暂存当前节点
            current.next = pre
            
            # 先移动pre,后移动current;否则容易造成指针指向问题
            pre = current
            current = temp
        return pre
递归法:
class Solution:
    # 这里的递归写法按照双指针法写即可
    def reverseList(self, head):
        # 递归写法
        return self.reverse(head, None)
    def reverse(self, cur, pre):    # 递归要有个初始化
        if cur == None:
            return pre
        temp = cur.next
        cur.next = pre
        return self.reverse(temp, cur)
复杂度:

时间复杂度: O ( n ) O(n) O(n),因为要循环遍历整个列表
空间复杂度: O ( 1 ) O(1) O(1)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值