LeetCode刷题计划_2

用数组实现一个顺序栈

用链表实现一个链式栈

编程模拟实现一个浏览器的前进、后退功能

队列

用数组实现一个顺序队列

用链表实现一个链式队列

实现一个循环队列

递归

编程实现斐波那契数列求值 f(n)=f(n-1)+f(n-2)

编程实现求阶乘 n!

编程实现一组数据集合的全排列

对应的 LeetCode 练习题

Valid Parentheses(有效的括号)

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

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/valid-parentheses
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

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

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

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

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

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

解题思路

遇到左括号则入栈,遇到右括号则将其与栈顶元素对比,如果可以匹配,则出栈,否则返回 False

代码
class Solution:
    def isValid(self, s: str) -> bool:
        dic = {'(':')', '{':'}', '[':']', '?':'?'}
        n = len(s)
        res = ['?']
        for i in range(n):
            if s[i] in dic:
                res.append(s[i])
            elif dic[res.pop()] != s[i]:
                return False
        return len(res) == 1
复杂度分析

时间复杂度:
空间复杂度:
/Todo

Longest Valid Parentheses(最长有效的括号)

LeetCode32
给定一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长的包含有效括号的子串的长度。

示例 1:
输入: “(()” 输出: 2
解释: 最长有效括号子串为 “()”

示例 2:
输入: “)()())”
输出: 4
解释: 最长有效括号子串为 “()()”

解题思路

左括号入栈,遇到右括号出栈,此时若栈为空,将当前标号压入;若不为空,当前标号与栈顶元素之差就是有效括号的长度。

代码
class Solution:
    def longestValidParentheses(self, s: str) -> int:
        stack = [-1]
        length = 0
        max_length = 0
        for i in range(len(s)):
            if s[i] == '(':
                stack.append(i)
            else:
                stack.pop()
                if stack == []:
                    stack.append(i)
                else:
                    length = i - stack[-1]
                    max_length = max(max_length, length)
        return max_length

复杂度分析

/Todo

Evaluate Reverse Polish Notatio(逆波兰表达式求值)

LeetCode 150

根据 逆波兰表示法,求表达式的值。

有效的运算符包括 +, -, *, / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。

说明:
整数除法只保留整数部分。
给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。

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

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

示例 3:
输入: [“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 + 2 ) * ( 3 + 4 ) 。 该算式的逆波兰表达式写法为 ( ( 1 2 + ) (
3 4 + ) * ) 。
逆波兰表达式主要有以下两个优点:

去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。
适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中。

解题思路

遇到数字则入栈,遇到操作符则取栈顶两个元素进行运算后放入栈中

代码
class Solution:
    def evalRPN(self, tokens: List[str]) -> int:
        res = []
        ans = 0
        n = len(tokens)
        s = ['+', '-', '*', '/']
        for c in tokens:
            if c not in s:
            #此处int(c)省了很多事,保证了res中全是整数了,可以直接进行运算
                res.append(int(c))
            elif c == '+':
                x = res.pop()
                res[-1] += x

            elif c == '-':
                x = res.pop()
                res[-1] -= x
            elif c == '*':
                x = res.pop()
                res[-1] *= x
            else:
                x = res.pop()
                # 除法要求的是整数,只好int强制转换一下类型
                res[-1] = int(res[-1] / x)
        return res[-1]
复杂度分析

需要遍历整个列表,时间复杂度为O(n)
入栈需要空间,空间复杂度也为O(n)

队列

Design Circular Deque(设计一个双端队列)

LeetCode 641

设计实现双端队列。

你的实现需要支持以下操作:

MyCircularDeque(k):构造函数,双端队列的大小为k。
insertFront():将一个元素添加到双端队列头部。 如果操作成功返回 true。
insertLast():将一个元素添加到双端队列尾部。如果操作成功返回 true。
deleteFront():从双端队列头部删除一个元素。 如果操作成功返回 true。
deleteLast():从双端队列尾部删除一个元素。如果操作成功返回 true。
getFront():从双端队列头部获得一个元素。如果双端队列为空,返回 -1。
getRear():获得双端队列的最后一个元素。 如果双端队列为空,返回 -1。
isEmpty():检查双端队列是否为空。
isFull():检查双端队列是否满了。

示例:

MyCircularDeque circularDeque = new MycircularDeque(3); // 设置容量大小为3
circularDeque.insertLast(1); // 返回 true
circularDeque.insertLast(2); // 返回 true
circularDeque.insertFront(3); // 返回 true
circularDeque.insertFront(4); // 已经满了,返回 false
circularDeque.getRear(); // 返回 2 circularDeque.isFull();
// 返回 true circularDeque.deleteLast(); // 返回 true
circularDeque.insertFront(4); // 返回 true
circularDeque.getFront(); // 返回 4

解题思路

熟悉一下怎么设计一个双端队列

代码
class MyCircularDeque:

    def __init__(self, k: int):
        """
        Initialize your data structure here. Set the size of the deque to be k.
        """
        self.max_len = k
        self.queue = []

        

    def insertFront(self, value: int) -> bool:
        """
        Adds an item at the front of Deque. Return true if the operation is successful.
        """
        if len(self.queue) < self.max_len:
            self.queue = self.queue[::-1]
            self.queue.append(value)
            self.queue = self.queue[::-1]
            return True
        return False
        

    def insertLast(self, value: int) -> bool:
        """
        Adds an item at the rear of Deque. Return true if the operation is successful.
        """
        if len(self.queue) < self.max_len:
            self.queue.append(value)
            return True
        return False
        

    def deleteFront(self) -> bool:
        """
        Deletes an item from the front of Deque. Return true if the operation is successful.
        """
        if self.queue:
            del self.queue[0]
            return True
        return False

    def deleteLast(self) -> bool:
        """
        Deletes an item from the rear of Deque. Return true if the operation is successful.
        """
        if self.queue:
            del self.queue[-1]
            return True
        return False

    def getFront(self) -> int:
        """
        Get the front item from the deque.
        """
        if self.queue:
            return self.queue[0]
        return -1
        

    def getRear(self) -> int:
        """
        Get the last item from the deque.
        """
        if self.queue:
            return self.queue[-1]
        return -1
        

    def isEmpty(self) -> bool:
        """
        Checks whether the circular deque is empty or not.
        """
        if len(self.queue) == 0:
            return True
        return False
        

    def isFull(self) -> bool:
        """
        Checks whether the circular deque is full or not.
        """
        if len(self.queue) == self.max_len:
            return True
        return False
复杂度分析

/Todo

Sliding Window Maximum(滑动窗口最大值)

LeetCode 239

给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回滑动窗口中的最大值。

进阶:

你能在线性时间复杂度内解决此题吗?

示例:

输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3 输出: [3,3,5,5,6,7]
解释:
在这里插入图片描述

提示:

1 <= nums.length <= 10^5
-10^4 <= nums[i] <= 10^4 1 <= k <= nums.length

解题思路

有关滑动窗口问题,可以看一下这篇文章:我写了套框架,把滑动窗口算法变成了默写题

代码
class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        deque = collections.deque()
        res = []
        for i, num in enumerate(nums):
            while deque and deque[0] <= i - k:
                deque.popleft()
            while deque and num > nums[deque[-1]]:
                deque.pop()
            deque.append(i)
            if i >= k - 1:
                res.append(nums[deque[0]])
        return res
复杂度分析

/Todo

递归

Climbing Stairs(爬楼梯)

LeetCode 70

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

示例 1:

输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。

  1. 1 阶 + 1 阶
  2. 2 阶

示例 2:

输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。

  1. 1 阶 + 1 阶 + 1 阶
  2. 1 阶 + 2 阶
  3. 2 阶 + 1 阶
解题思路

直接递归,加个缓存装饰器就不会出现超时问题
f ( n ) = f ( n − 1 ) + f ( n − 2 ) f(n) = f(n-1) + f(n-2) f(n)=f(n1)+f(n2)

代码
class Solution:
    @functools.lru_cache(100)
    def climbStairs(self, n: int) -> int:
        if n == 1:
            return 1
        if n == 2:
            return 2
        return self.climbStairs(n-1) + self.climbStairs(n-2)
复杂度分析

/Todo

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值