算法训练第三天 | 链表 203.移除链表元素、707.设计链表、206.反转链表

LeetCode 203.移除链表元素

题目链接

203.移除链表元素

思路

两种方式删除链表
一:不用虚拟头节点。删除的元素在头节点,直接让head=head.next。删除的元素不在头节点,设置一个移动指针cur指向头节点,开始让cur.next = cur.next.next。(注意两次操作都要先判空,因为不可以操作空指针)
二、用虚拟头节点。设置移动指针cur = dummyhead,同上表述的步骤二(不需要再判断删除元素是否在头节点,代码更简洁)
代码如下:
(不用虚拟头节点的没写出来,但是小趴菜还没找到原因,先贴出来,方便的话欢迎懂的盆友评论指出,救救小趴菜)

# 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]:
        #不用虚拟头节点
        while (head != None) and (head.val == val):
                head = head.next
        cur = head
        while cur.next != None:
            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]:
        #带虚拟头节点
        dummyhead = ListNode(next = head)
        cur = dummyhead
        while cur.next != None:
            if cur.next.val == val:
                cur.next = cur.next.next
            else:
                cur = cur.next
        return dummyhead.next

反思

不懂是python 的原因还是啥,感觉不用虚拟头指针的思路是对的,但是无法通过。还是用虚拟头指针会方便很多,因为流程是一样的,不用多做一个情况判断

LeetCode 707.设计链表

题目链接

707.设计链表

思路

(单链表的)

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

class MyLinkedList:

    def __init__(self):
        self.head = Node()
        self.size = 0

    def get(self, index: int) -> int:
        cur = self.head.next
        if index<0 or index>=self.size:
            return -1
        else:
            while index:
                cur = cur.next
                index -= 1
            return cur.val
        
    def addAtHead(self, val: int) -> None:
        newnode = Node(val)
        newnode.next = self.head.next
        self.head.next = newnode
        self.size += 1

    def addAtTail(self, val: int) -> None:
        newnode = Node(val)
        cur = self.head
        '''n = self.size
        if self.size == 0:
            self.head.next = newnode
        else:
            while n:
                cur = next
                n -= 1
            cur.next = newnode'''
        while cur.next:
            cur = cur.next
        cur.next = newnode
        self.size += 1

    def addAtIndex(self, index: int, val: int) -> None:
        newnode = Node(val)
        cur = self.head
        if index < 0:
            self.addAtHead(val)
            return
        elif index == self.size:
            self.addAtTail(val)
            return
        elif index > self.size:
            return

        while index:
            cur = cur.next
            index -= 1
        newnode.next = cur.next
        cur.next = newnode
        self.size += 1

    def deleteAtIndex(self, index: int) -> None:
        cur = self.head
        if index < 0 or index >= self.size:
            return
        else:
            while index:
                cur = cur.next
                index -= 1
            cur.next = cur.next.next
            self.size -= 1

(双链表的)

class Node:
    def __init__(self, val=0):
        self.val = val
        self.next = None
        self.prev = None   #新增的指向上一个节点

class MyLinkedList:    

    def __init__(self):
        self.head, self.tail = Node(), Node()  #增加了一个虚拟尾指针
        self.head.next, self.tail.prev = self.tail, self.head
        self.size = 0

    def _getNode(self, index: int) -> Node:
        #如果index大于长度的一半,则从尾巴开始找比较快,反之从头更快
        if index >= (self.size // 2):
            cur = self.tail.prev
            for _ in range(self.size - index - 1):
                cur = cur.prev
        else:
            cur = self.head.next
            for _ in range(index):
                cur = cur.next
        return cur
        
    def get(self, index: int) -> int:
        #如果index大于长度的一半,则从尾巴开始找比较快,反之从头更快
        if index<0 or index>=self.size:
            return -1
        else:
            cur = self._getNode(index)
            return cur.val
        
    def addAtHead(self, val: int) -> None:
        newnode = Node(val)
        if self.head.next != None:
            self.head.next.prev = newnode
        newnode.next = self.head.next
        newnode.prev = self.head
        self.head.next = newnode
        self.size += 1

    def addAtTail(self, val: int) -> None:
        newnode = Node(val)
        newnode.prev = self.tail.prev
        self.tail.prev.next = newnode
        newnode.next = self.tail
        self.tail.prev = newnode
        self.size += 1

    def addAtIndex(self, index: int, val: int) -> None:
        newnode = Node(val)
        if index < 0:
            self.addAtHead(val)
            return
        elif index == self.size:
            self.addAtTail(val)
            return
        elif index > self.size:
            return

        a = self._getNode(index)
        a.prev.next = newnode
        newnode.prev = a.prev
        newnode.next = a
        a.prev = newnode
        self.size += 1

    def deleteAtIndex(self, index: int) -> None:
        if index < 0 or index >= self.size:
            return
        else:
            a = self._getNode(index)
            a.prev.next = a.next
            a.next.prev = a.prev
            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)

反思

对于链表的基本操作:增删查,增分为头插和尾插。双链表比单链表做操作更方便,因为增加了一个向前指的指针(记得双链表要增加一个虚拟尾节点)

LeetCode 206.反转链表

题目链接

206.反转链表

思路

暴力方案是找到最后一个节点,一个一个往前,塞进一个新的链表里面,打印新链表
卡哥思路:利用双指针。一个指向当前节点,一个指向前一个节点,让当前节点的next指向前一个节点,直到当前节点为空

# 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
        prev = None
        while cur:
            temp = cur.next
            cur.next = prev
            prev = cur
            cur = temp
        return prev
            

(更简洁的代码是整理成递归代码,思路还是双指针)

class Solution:
    def reverse(self, cur, prev):
        if cur == None:
            return prev
        temp = cur.next
        cur.next = prev
        return self.reverse(temp, cur)
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        return self.reverse(head, None)

反思

反转链表主要通过双指针思想,改变指针的指向,让原本向后指的指针向前。自己想的时候过于复杂,一个一个节点遍历出来还要建一个新的链表,直接再原链表基础上改变方向即达到需求

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值