Python数据结构+LeetCode(二)


一、栈

(一)栈的思想

  • 栈(有时称为“后进先出栈”)是一个项的有序集合,其中添加移除新项总发生在同一端。这一端通常称为“顶部”。与顶部对应的端称为“底部”。
  • 栈的底部很重要,因为在栈中靠近底部的项是存储时间最长的。最近添加的项是最先会被移除的。这种排序原则有时被称为 LIFO,后进先出。它基于在集合内的时间长度做排序。较新的项靠近顶部,较旧的项靠近底部。
class Stack:
  def __int__(self):
    self.items = []
  def push(self,item):
    self.items.append(item)
  def pop(self):
    return self.items.pop()
  def peek(self):
    return self.items[len(self.items)-1]
  def size(self):
    return len(self.items)
  def isEmpty(self):
    return self.items == []

(二)代码

  • Example 1
    在这里插入图片描述
    在这里插入图片描述
class Solution:
    def trap(self, height: List[int]) -> int:
        if len(height) <= 2:
            return 0
        ans,current,stack = 0,0,[]
        while current < len(height):
            while len(stack) != 0 and height[current] > height[stack[-1]]:
                top = stack.pop()
                if len(stack) == 0:
                    break
                distance = current - stack[-1] -1
                bounded_height = min(height[current],height[stack[-1]])-height[top]
                ans = ans + distance * bounded_height
            stack.append(current)
            current = current+1
        return ans
  • Example 2
    • 给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串 s ,判断字符串是否有效。
    • 有效字符串需满足:
      • 左括号必须用相同类型的右括号闭合。
      • 左括号必须以正确的顺序闭合。
class Solution:
    def isValid(self, s: str) -> bool:
        stack = []
        for item in s:
            if item == "(" or item == "[" or item == "{":
                stack.append(item)
            elif item == ")":
                if len(stack) != 0 and stack[-1] == "(":
                    stack.pop()
                else:
                    return False
            elif item == "]":
                if len(stack) != 0 and stack[-1] == "[":
                    stack.pop()
                else:
                    return False
            elif item == "}" :
                if len(stack) != 0 and stack[-1] == "{":
                    stack.pop()
                else:
                    return False
        return len(stack) == 0
  • Example 3
    在这里插入图片描述

    • 具体做法是我们始终保持栈底元素为当前已经遍历过的元素中「最后一个没有被匹配的右括号的下标」,这样的做法主要是考虑了边界条件的处理,栈里其他元素维护左括号的下标:
    • 对于遇到的每个‘(’,我们将它的下标放入栈中
      对于遇到的每个‘)’,我们先弹出栈顶元素表示匹配了当前右括号:
      • 如果栈为空,说明当前的右括号为没有被匹配的右括号,我们将其下标放入栈中来更新我们之前提到的「最后一个没有被匹配的右括号的下标」
      • 如果栈不为空,当前右括号的下标减去栈顶元素即为「以该右括号为结尾的最长有效括号的长度」
      • 我们从前往后遍历字符串并更新答案即可。
    • 需要注意的是,如果一开始栈为空,第一个字符为左括号的时候我们会将其放入栈中,这样就不满足提及的「最后一个没有被匹配的右括号的下标」,为了保持统一,我们在一开始的时候往栈中放入一个值为-1的元素。
class Solution:
    def longestValidParentheses(self, s: str) -> int:
        # 判断是不是空字符串
        if not s:
            return 0
        res = 0
        stack = [-1]
        for i in range(len(s)):
            if s[i] == "(":
                # 把"("的index装进stack
                stack.append(i)
            else:
                stack.pop() 
                if not stack:
                    # 如果stack是空的,就把")"的index装进stack
                    # 即把不合格的index放进stack
                    stack.append(i)
                else:
                    res = max(res,i - stack[-1])
        return res

二、队列

(一)队列的思想

  • 队列是项的有序结合,其中添加新项的一端称为队尾,移除项的一端称为队首。当一个元素从队尾进入队列时,一直向队首移动,直到它成为下一个需要移除的元素为止。
  • 最近添加的元素必须在队尾等待。集合中存活时间最长的元素在队首,这种排序成为 FIFO,先进先出,也被成为先到先得。
class Queue:
    def __int__(self):
        self.items = []
    def isEmpty(self):
        return len(self.items) == 0
    def enqueue(self,item):
        self.items.insert(0,item)
    def dequeue(self):
        return self.items.pop()
    def size(self):
        return len(self.items)

(二)双端队列(Deque)的思想

  • deque(也称为双端队列)是与队列类似的项的有序集合。它有两个端部,首部和尾部,并且项在集合中保持不变。
  • deque不同的地方是添加和删除项是非限制性的。可以在前面或后面添加新项。同样,可以从任一端移除现有项。在某种意义上,这种混合线性结构提供了单个数据结构中的栈和队列的所有能力。
class Deque:
    def __int__(self):
        self.items = []
    def addFront(self,item):
        self.items.insert(0,item)
    def addRear(self,item):
        self.items.append(item)
    def removeFront(self):
        self.items.pop(0)
    def removeRear(self):
        self.items.pop()
    def isEmpty(self):
        return len(self.items) == 0
    def size(self):
        return len(self.items)

(三) 代码

  • 使用 deque 数据结构可以容易地解决经典回文问题。回文是一个字符串,读取首尾相同的字符,例如, radar toot madam 。
  • 我们想构造一个算法输入一个字符串,并检查它是否是一个回文。
    • 我们可以直接删除并比较首尾字符,只有当它们匹配时才继续。
    • 如果可以持续匹配首尾字符,我们最终要么用完字符, 要么留出大小为 1 的deque,取决于原始字符串的长度是偶数还是奇数。
def palchecker(String):
    Deque = []
    for s in String:
        Deque.append(s)
    Judge = True
    while len(Deque) > 1 and Judge:
        left = Deque.pop(0)
        right = Deque.pop()
        if left != right:
            Judge = False
            return Judge
    return Judge
print(palchecker("lsdkjfskf"))
print(palchecker("radar"))

三、列表

(一)列表的思想——ListNode

  • 链表实现的基本构造块是节点。每个节点对象必须至少保存两个信息。首先,节点必须包含列表项本身。我们将这个称 为节点的数据字段。此外,每个节点必须保存对下一个节点的引用。
class Node:
    def __int__(self,initData):
        self.data = initData
        self.next = None
    def getData(self):
        return self.data
    def getNext(self):
        return self.next
    def setData(self,data):
        self.data = data
    def setNext(self,nextNode):
        self.next = nextNode
  • 无序列表将从一组节点构建,每个节点通过显式引用链接到下一个节点。只要我们知道在哪里找到第一个节点(包含第一个项),之后的每个项可以通过连续跟随下一个链接找到。考虑到这一点,UnorderedList 类必须保持对第一个节点的引用。Listing 2 显示了构造函数。注意,每个链表对象将维护对链表头部的单个引用。
class UnorderedList:
    def __init__(self):
        self.head = None
    def isEmpty(self):
        return self.head == None
    def add(self,item):
        temp = Node(item)
        temp.setNext(self.head)
        self.head = temp
    def count(self):
        current = self.head
        num = 0
        while current != None:
            num = num + 1
            current = current.getNext()
        return num
    def search(self,item):
        current, isFind = self.head, False
        while current != None and isFind == False:
            if current.getData() == item:
                isFind = True
            else:
                current = current.getNext()
        return isFind
    def remove(self,item):
        current,previous,isRemove = self.head,None,False
        while isRemove == False:
            if current.getData() == Data:
                isRemove = True
            else:
                previous = current
                current = current.getNext()
        if previous == None:
            self.head = current.getNext()
        else:
            previous.setNext(current.getNext())
  • 有序列表,我们必须记住项的相对位置是基于一些潜在的特性。
    • 当我们考虑有序列表的操作时,我们应该注意,isEmpty和size方法可以与无序列表一样实现,因为它们只处理链表中的节点数量,而不考虑实际项值。同样, remove方法将正常工作,因为我们仍然需要找到该项,然后删除它。剩下的两个方法,search和add,将需要一些修改。
    • 搜索无序列表需要我们一次遍历一个节点,直到找到我们正在寻找的节点或者没找到节点(None)。事实证明,相同的方法在有序列表也有效。然而,在项不在链表中的情况下,我们可以利用该顺序来尽快停止搜索。
class OrderList:
    def __int__(self):
        self.head = None
    def isEmpty(self):
        return self.head == None
    def size(self):
        current,num = self.head,0
        while current != None:
            num = num + 1
            current = current.getNext()
        return num
    def remove(self,item):
        current,previous,isRemove = self.head, None, False
        while isRemove == False:
            if current.getData() == item:
                isRemove = True
            else:
                previous = current
                current = current.getNext()
        if previous == None:
            self.head = current.getNext()
        else:
            previous.setNext(current.getNext())
    def search(self,item):
        current, isFind = self.head, False
        while current != None and isFind == False:
            if current.getData() == item:
                isFind = True
            else:
                if item > current.getData():
                    break
                else:
                    current = current.getNext()
        return isFind
    def add(self,item):
        current, previous, Stop = self.head, None, False
        while current != None and Stop == False:
            if current.getData()>item:
                Stop = True
            else:
                previous = current
                current = current.getNext()
        temp = Node(item)
        if previous == None:
            temp.setNext(self.head)
            self.head = temp
        else:
            previous.setNext(temp)
            temp.setNext(current)

(二)代码

  • 给你两个非空的链表,表示两个非负的整数。它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储一位数字。请你将两个数相加,并以相同形式返回一个表示和的链表。你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
    • 示例1:
      • 输入:l1 = [2,4,3], l2 = [5,6,4]
      • 输出:[7,0,8]
      • 解释:342 + 465 = 807.
    • 示例2:
      • 输入:l1 = [0], l2 = [0]
      • 输出:[0]
    • 示例3:
      • 输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
      • 输出:[8,9,9,9,0,0,0,1]
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        res, left = ListNode(0), 0
        re = res
        while l1 != None or l2 != None:
            x= l1.val if l1 else 0
            y= l2.val if l2 else 0
            s = x+y+left
            left = s//10
            re.next=ListNode(s%10)
            re = re.next
            if(l1!=None):l1=l1.next
            if(l2!=None):l2=l2.next
        if left != 0:
            re.next = ListNode(1)
        return res.next
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值