代码编织梦想

LeetCode刷题——栈(python语言)

一、栈

1.1 定义

栈(Stack):也称堆栈。一种线性表数据结构,是一种只允许在表的一端进行插入和删除操作的线性表。
在这里插入图片描述
我们把栈中允许插入和删除的一端称为[栈顶(top)];另一端则称为[栈底(bottom)]。当表中没有任何数据元素时,称之为[空栈]。
栈的特点:

  1. 线性表
  2. 后进先出
    栈的存储方式有顺序栈和链式栈。

1.2 栈的基本操作

  1. 初始化空栈
  2. 判断栈是否为空
  3. 判断栈是否已满
  4. 插入元素
  5. 删除元素
  6. 获取栈顶元素

1.3 栈的顺序存储实现代码

class Stack:
	#初始化空栈
	def __init__(self,size=100):
		self.stack = []
		self.size = size
		self.top = -1
	
	#判断栈是否为空
	def is_empty(self):
		return self.top == -1
	
	#判断栈是否已满
	def is_full(self):
		return self.top + 1 == self.size
	
	#入栈操作
	def push(self,value):
		if self.is_full():
			raise Exception('Stack is full')
		else:
			self.stack.append(value)
			self.top += 1
	
	#出栈操作
	def pop(self):
		if self.is_empty():
			raise Exception('Stack is empty')
		else:
			self.top -= 1
			self.stack.pop()
		
	#获取栈顶元素
	def peek(self):
		if self.is_empty():
			raise Exception('Stack is empty')
		else:
			return self.stack(self.top)

1.4 栈的链式存储实现代码

class Node:
	def __init__(self,value):
		self.value = value
		self.next = next
	
class Stack:
	#初始化空栈
	def __init__(self):
		self.top = None

	#判断栈是否为空
	def is_empty(self):
		return self.top == None
	
	#入栈操作(类似于头插法)
	def push(self,value):
		cur = Node(value)
		cur.next = self.top
		self.top = cur

	#出栈操作
	def pop(self):
		if self.is_empty():
			raise Exception('Stack is empty')
		else:
			cur = self.top
			self.top = self.top.next
			del cur #删除栈顶元素

	#获取栈顶元素
	def peek(self):
		if self.is_empty():
			raise Exception('Stack is empty')
		else:
			return self.top.value

二、刷题

2.1 有效的括号

给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串 s ,判断字符串是否有效。

有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。

示例 1:
输入:s = “()”
输出:true

示例 2:
输入:s = “()[]{}”
输出:true

示例 3:
输入:s = “(]”
输出:false

示例 4:
输入:s = “([)]”
输出:false

示例 5:
输入:s = “{[]}”
输出:true

提示:
1 <= s.length <= 104
s 仅由括号 ‘()[]{}’ 组成

#首先计算字符串长度,如果是奇数,返回False。首先,找到左侧括号,入栈,右括号且在栈顶,出栈。
class Solution:
    def isValid(self, s: str) -> bool:
        if(len(s)%2==1):
            return False
        stack = []
        for ch in s:
            if(ch == '(' or ch == '{' or ch=='['):
                stack.append(ch)
            elif(ch == ')'):
                if(len(stack)!=0 and stack[-1]=='('):
                    stack.pop()
                else:
                    return False
            elif(ch=='}'):
                if(len(stack)!=0 and stack[-1]=='{'):
                    stack.pop()
                else:
                    return False
            elif(ch==']'):
                if(len(stack)!=0 and stack[-1]=='['):
                    stack.pop()
                else:
                    return False
        if(len(stack)==0): #长度为0,说明全部匹配,成功匹配
            return True
        else:
            return False

2.2 逆波兰表达式求值

根据 逆波兰表示法,求表达式的值。
有效的算符包括 +、-、*、/ 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
注意 两个整数之间的除法只保留整数部分。
可以保证给定的逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。

示例 1:
输入:tokens = [“2”,“1”,"+",“3”,"*"]
输出:9
解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9

示例 2:
输入:tokens = [“4”,“13”,“5”,"/","+"]
输出:6
解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6

示例 3:
输入:tokens = [“10”,“6”,“9”,“3”,"+","-11","","/","",“17”,"+",“5”,"+"]
输出:22
解释:该算式转化为常见的中缀算术表达式为:
((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22

提示:
1 <= tokens.length <= 104
tokens[i] 是一个算符("+"、"-"、"*" 或 “/”),或是在范围 [-200, 200] 内的一个整数

逆波兰表达式:
逆波兰表达式是一种后缀表达式,所谓后缀就是指算符写在后面。
平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 ) 。
该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * ) 。
逆波兰表达式主要有以下两个优点:
去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。
适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中。

#根据逆波兰式,一次一次计算结果
class Solution:
    def evalRPN(self, tokens: List[str]) -> int:
        stack = []
        for ch in tokens:
            if(ch == '+'):
                stack.append(stack.pop() + stack.pop())
            elif(ch == '-'):
                stack.append(-stack.pop() + stack.pop())
            elif(ch == '*'):
                stack.append(stack.pop()*stack.pop())
            elif(ch=='/'):
                stack.append(int(1/stack.pop()*stack.pop()))
            else:
                stack.append(int(ch))
        return stack.pop()

2.3 最小栈

设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

push(x) —— 将元素 x 推入栈中。
pop() —— 删除栈顶的元素。
top() —— 获取栈顶元素。
getMin() —— 检索栈中的最小元素。

示例:
输入:
[“MinStack”,“push”,“push”,“push”,“getMin”,“pop”,“top”,“getMin”]
[[],[-2],[0],[-3],[],[],[],[]]

输出:
[null,null,null,null,-3,null,0,-2]

解释:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.getMin(); --> 返回 -2.

提示:
pop、top 和 getMin 操作总是在 非空栈 上调用。

#用列表模拟栈,取最小值的时候选取排序后列表的第一个元素。
class MinStack:

    def __init__(self):
        self.stack = []
        
    def push(self, val: int) -> None:
        self.stack.append(val)

    def pop(self) -> None:
        self.stack.pop()

    def top(self) -> int:
        return self.stack[-1]

    def getMin(self) -> int:
        if(len(self.stack)>0):
            return sorted(self.stack)[0]
        else:
            return None
#340 ms	18.1 MB
#3 2
#不用sorted,可以把每次找的最小值记录在一个栈里min_stack.大小和stack一样。
class MinStack:
    def __init__(self):
        self.stack = []
        self.min_stack = [math.inf]
    def push(self, val: int) -> None:
        self.stack.append(val)
        self.min_stack.append(min(self.min_stack[-1],val))
    def pop(self) -> None:
        self.stack.pop()
        self.min_stack.pop()#最小数的栈的大小与栈的大小相同,统一删除
    def top(self) -> int:
        return self.stack[-1]
    def getMin(self) -> int:

        return self.min_stack[-1]
#48 ms	18.2 MB

2.4 基本计算器 II

给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。
整数除法仅保留整数部分。

示例 1:
输入:s = “3+2*2”
输出:7

示例 2:
输入:s = " 3/2 "
输出:1

示例 3:
输入:s = " 3+5 / 2 "
输出:5

提示:
1 <= s.length <= 3 * 105
s 由整数和算符 (’+’, ‘-’, ‘*’, ‘/’) 组成,中间由一些空格隔开
s 表示一个 有效表达式
表达式中的所有整数都是非负整数,且在范围 [0, 231 - 1] 内
题目数据保证答案是一个 32-bit 整数

#通过第一位的加号对符号处理,最后求和
class Solution:
    def calculate(self, s: str) -> int:
        n = len(s)
        stack = []
        preSigh = '+' #第一个数的前面自带一个加号。
        num = 0
        for i in range(n):
            if(s[i]!=' ' and s[i].isdigit()):
                num = num*10 - ord('0') + ord(s[i]) #处理多位数字符
            if(i == n-1 or s[i] in '+-*/'):#遍历到符号,或者最后分别处理
                if (preSigh == '+'): 
                    stack.append(num)
                elif (preSigh =='-'):
                    stack.append(-num)
                elif (preSigh == '*'):
                    stack.append(stack.pop()*num)
                else:
                    stack.append(int(stack.pop()/num))
                preSigh = s[i]
                num =0 
        return sum(stack)
#72 ms	16.9 MB

2.5 比较含退格的字符串

给定 s 和 t 两个字符串,当它们分别被输入到空白的文本编辑器后,请你判断二者是否相等。# 代表退格字符。
如果相等,返回 true ;否则,返回 false 。
注意:如果对空文本输入退格字符,文本继续为空。

示例 1:
输入:s = “ab#c”, t = “ad#c”
输出:true
解释:S 和 T 都会变成 “ac”。

示例 2:
输入:s = “ab##”, t = “c#d#”
输出:true
解释:s 和 t 都会变成 “”。

示例 3:
输入:s = “a##c”, t = “#a#c”
输出:true
解释:s 和 t 都会变成 “c”。

示例 4:
输入:s = “a#c”, t = “b”
输出:false
解释:s 会变成 “c”,但 t 仍然是 “b”。

提示:
1 <= s.length, t.length <= 200
s 和 t 只含有小写字母以及字符 ‘#’

进阶:
你可以用 O(N) 的时间复杂度和 O(1) 的空间复杂度解决该问题吗?

#1:用两个栈,分别根据#对列表处理,然后比较是否相等
class Solution:
    def backspaceCompare(self, s: str, t: str) -> bool:
        stack_s = []
        stack_t = []
        for ch in s:
            if(ch != '#'):
                stack_s.append(ch)
            elif(len(stack_s)!=0):
                stack_s.pop()
        for ch in t:
            if(ch != '#'):
                stack_t.append(ch)
            elif(len(stack_t)!=0):
                stack_t.pop()
        if(len(stack_s)!=len(stack_t)):
            return False
        for i in range(len(stack_s)):
            if(stack_s[i]!=stack_t[i]):
                return False
        return True
#36 ms	15.2 MB
#2 
class Solution:
    def backspaceCompare(self, s: str, t: str) -> bool:
        stack_s = []
        stack_c = []
        for i in s:
            if i != '#':
                stack_s.append(i)
            else:
                if not stack_s:
                    continue
                stack_s.pop()


        for i in t:
            if i != '#':
                stack_c.append(i)
            else:
                if not stack_c:
                    continue
                stack_c.pop()
        

        return True if ''.join(stack_s)==''.join(stack_c) else False #直接连接起来比较
#36 ms	15.2 MB
        
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_26274961/article/details/123011952

leetcode刷题——day1_哈哈哈哈士奇vip的博客-爱代码爱编程

一边看算法,一边刷题吧,先从简单的开始: 刷题之路这就开始了? 561. Array Partition I Given an array of 2n integers, your task is to group t

leetcode刷题笔记(python)——leetcode使用介绍(转)_不会编程的峰峰的博客-爱代码爱编程

转载自https://blog.csdn.net/seabiscuityj/article/details/80730733        这段时间看论文看得非常麻木,有点看不下去的感觉,所以打算刷一刷LeetCode,复习一下python语法,同时找一找编程思维。       LeetCode刷题笔记用来记录我自己的刷题过程和一些解题思路,争取将每一题的代码、注释和思考过

【LeetCode刷题-简单】155. 最小栈(python c++)-爱代码爱编程

题目 设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。       push(x) -- 将元素 x 推入栈中。    pop() -- 删除栈顶的元素。    top() -- 获取栈顶元素。    getMin() -- 检索栈中的最小元素。示例: MinStack minStack = new MinS

leetcode刷题日记----栈(python)-爱代码爱编程

单调栈适合解决两边大小决定中间特征的问题 柱状图中最大矩形 题目描述: 给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的矩形的最大面积。 思路分析:这题的关键在于以某个点B为高的矩形的最大宽度为该点左边第一个小于它的点a到右边最靠近它且比其小的点c。 单调栈的特点在

Leetcode:1441. 用栈操作构建数组(栈)-爱代码爱编程

1441. 用栈操作构建数组 给你一个目标数组 target 和一个整数 n。每次迭代,需要从 list = {1,2,3…, n} 中依序读取一个数字。 请使用下述操作来构建目标数组 target : Push:从 list 中读取一个新元素, 并将其推入数组中。 Pop:删除数组中的最后一个元素。 如果目标数组构建完成,就停止读取更多元素。 题目

150. 逆波兰表达式求值-爱代码爱编程

根据逆波兰表示法,求表达式的值。 有效的运算符包括 +, -, *, / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。 说明: 1.整数除法只保留整数部分。 2.给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。 示例 1: 示例 2: 示例 3: 逆波兰表达式: 逆波兰表达式是一种后缀表达式,所谓后缀就是指

leetcode刷题可以用python吗_LeetCode刷题——第四天(python)-爱代码爱编程

每天选壁纸做封面这个环节是我最喜欢的,今天的题目是比较经典又十分简单的一道题。 第四天——第四题(回文数) 请看题:判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。 示例1: 输入: 121 输出: true 示例2: 输入: -121 输出: false 解释: 从左向右读, 为 -121 。

leetcode python刷题_LeetCode刷题——第一天(python)-爱代码爱编程

今天是7月1日的晚上,作为研一小白,接下来的一段时间里希望自己每天都可以在LeetCode上刷几道题,这个平台也是我寻寻觅觅多个刷题平台后,相比较下来更适合我的一个编程实践平台。题量多,题目简单,阶梯训练,相信我坚持刷下去,编程能力多少会有所提高。 今天只做了一道题,因为外边快要下雨了,抓紧时间写一下就准备回家。。。。。。 第一天——第一题(两数之

LeetCode刷题——排序(python语言)-爱代码爱编程

LeetCode刷题——排序(python语言) 一、排序 顾名思义,排序就是将数组按照从小到大的顺序排列。 广义的排序分为内部排序方法和外部排序方法。 排序的方法有很多种,常用的冒泡、选择、插入、希尔、归并、快速、堆、计数、桶、基数排序。 按照时间复杂度划分: O

LeetCode刷题——数组(python语言)-爱代码爱编程

LeetCode刷题——数组(python语言) 一、数组 1.1 数组的定义 数组是具有一定顺序关系的若干对象组成的集合,组成数组的对象称为数组元。其中向量对应一维数组,矩阵对应二维数组。 1.2 数组的存储特点 数组在内存中按照顺序连续存储二维数组的分配按照行(C,C++,C#)来分配数组名表示的是数组的首地址,是常量二、刷题 2.1 两数

LeetCode刷题——树(python语言)-爱代码爱编程

LeetCode刷题——树(python语言) 一、树 数其实就是链表的拓展,将链表的后指针的一个跟改为多个。树已经不是线性结构了。其中最为经典的就是二叉树。如下图所示,即为一个二叉树。其中1为根节点,2为左子树,3为右子树。遍历树的方法与图类似,有深度优先搜索(DFS),利用栈来存储节点(后进先出),和广度优先搜索(BFS),利用队列来存储节点(先进

LeetCode刷题——搜索(python语言)-爱代码爱编程

LeetCode刷题——搜索(python语言) 一、搜索 搜索简单来说分为查找和遍历。 查找分为有序查找(二分查找)和无序查找(顺序查找,二叉搜索树)。 顺序查找:一个挨一个找,从头找到尾,属于暴力算法。效率低 二叉搜素树,保证一个条件就是左子树的值小于根节点的值小于右子树的值。这样中序遍历获得从小到大的元素 二分查找:前提是已经排好序,可以

LeetCode刷题——分治(python语言)-爱代码爱编程

LeetCode刷题——分治(python语言) 一、分治 分治就是分而治之,对于一个复杂的问题,划分为规模较小的相同的问题(相互独立,如果不独立,最好用动态规划),以便各个击破。 典型的例子就是归并排序,现将数组不断平均划分,直到最后分为两个元素,比较大小,将求出的小规模的解合并为一个大规模的解,自底向上求出大规模问题的解。 二、刷题 2.1 将

LeetCode刷题——哈希表(python语言)-爱代码爱编程

LeetCode刷题——哈希表(python语言) 一、哈希表 1.1 哈希表的概念 哈希表,也叫散列表。其实可以很像python的字典,也就是键(key)值(Hash(key))对,最简单也最常用的哈希表就是索引与索引的值具有一定的对应关系,(哈希函数)也就是说,a[0]=3代表数组中元素0的个数为3,可以看到哈希表大部分都被用来统计数据。而a[i