当前位置 博文首页 > Simon¥的博客:2020.09.21-2020.09.26 leetcode刷题总结(栈&am

    Simon¥的博客:2020.09.21-2020.09.26 leetcode刷题总结(栈&am

    作者:[db:作者] 时间:2021-09-04 21:22

    一.题目列表
    1.下一个更大元素 I
    题目描述:
    给定两个 没有重复元素 的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。找到 nums1 中每个元素在 nums2 中的下一个比其大的值。
    nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出 -1 。

    示例:
    输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
    输出: [-1,3,-1]
    解释:
    对于num1中的数字4,你无法在第二个数组中找到下一个更大的数字,因此输出 -1。
    对于num1中的数字1,第二个数组中数字1右边的下一个较大数字是 3。
    对于num1中的数字2,第二个数组中没有下一个更大的数字,因此输出 -1。

    题解:
    先对nums2中的每一个元素都找出比它大的值,用hashmap存储该数据,然后根据nums1中的数字顺序输出该值。定义一个栈,对nums2进行循环遍历,while栈不为空并且nums2[i]>栈顶元素,就将该元素和nums[2]的值放入hashmap。然后将nums2[i]入栈。循环结束后若栈不为空,则栈中与元素对应的hashmap都为-1.

    2.下一个更大元素 Ⅱ
    题目描述:
    给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。

    示例:
    输入: [1,2,1]
    输出: [2,-1,2]
    解释: 第一个 1 的下一个更大的数是 2;
    数字 2 找不到下一个更大的数;
    第二个 1 的下一个最大的数需要循环搜索,结果也是 2。

    题解:
    对nums中的每一个元素都找出比它大的值,用hashmap存储该数据。定义一个栈,对nums2*2进行循环遍历,当栈不为空并且nums2[i%nums.length()]>栈顶元素,如果hashmap中没有该nums[i]的值,就将该元素和nums[i%nums.length()]的值放入hashmap,。如果不是,则将nums2[i]入栈。循环结束后若栈不为空且hashmap中没有该元素,则栈中与元素对应的hashmap都为-1。
    优化:可以省略hashmap直接定义一个数组,将res的所有值初始化为-1。如果小,则res[stack.pop()]=nums[i]。然后将i%num.length()入栈。

    3.删除最外层的括号

    题目描述:
    有效括号字符串为空 ("")、"(" + A + “)” 或 A + B,其中 A 和 B 都是有效的括号字符串,+ 代表字符串的连接。例如,"","()","(())()" 和 “(()(()))” 都是有效的括号字符串。
    如果有效字符串 S 非空,且不存在将其拆分为 S = A+B 的方法,我们称其为原语(primitive),其中 A 和 B 都是非空有效括号字符串。
    给出一个非空有效字符串 S,考虑将其进行原语化分解,使得:S = P_1 + P_2 + … + P_k,其中 P_i 是有效括号字符串原语。
    对 S 进行原语化分解,删除分解中每个原语字符串的最外层括号,返回 S 。

    示例:
    输入:"(()())(())"
    输出:"()()()"
    解释:
    输入字符串为 “(()())(())”,原语化分解得到 “(()())” + “(())”,
    删除每个部分中的最外层括号后得到 “()()” + “()” = “()()()”。

    题解:
    定义一个辅助栈和一个字符串,对string进行循环遍历,当为"(",若栈不为空,则加入str。然后入栈。当为")",先将栈顶元素出栈,若栈不为空,则加入str。

    4.包含min函数的栈
    题目描述:
    定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。

    示例:
    MinStack minStack = new MinStack();
    minStack.push(-2);
    minStack.push(0);
    minStack.push(-3);
    minStack.min(); --> 返回 -3.
    minStack.pop();
    minStack.top(); --> 返回 0.
    minStack.min(); --> 返回 -2.

    题解:
    定义一个栈和一个辅助栈,当压入元素比辅助栈栈顶小或者辅助栈为空,则将其加入辅助栈中,出栈时的值若==min则将辅助栈也出栈。

    5.逆波兰表达式求值
    题目描述:
    有效的运算符包括 +, -, *, / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。

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

    题解:

    6..删除字符串中的所有相邻重复项
    题目描述:
    给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
    在 S 上反复执行重复项删除操作,直到无法继续删除。
    在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

    示例:
    输入:“abbaca”
    输出:“ca”
    解释:
    例如,在 “abbaca” 中,我们可以删除 “bb” 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 “aaca”,其中又只有 “aa” 可以执行重复项删除操作,所以最后的字符串为 “ca”。

    题解:

    7.每日温度
    题目描述:
    请根据每日 气温 列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用 0 来代替。

    示例:
    例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。
    提示:气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 [30, 100] 范围内的整数。

    题解:
    入栈的变为列表下标

    8.用两个栈实现队列
    题目描述:
    用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )

    示例:
    输入:
    [“CQueue”,“appendTail”,“deleteHead”,“deleteHead”]
    [[],[3],[],[]]
    输出:[null,null,3,-1]

    题解:

    二.相关语法及用法
    单调栈
    stack.pop() stack.peek() stack.push()
    最小栈
    链栈

    队列

    一.题目列表
    1.字符串解码
    题目描述:
    给定一个经过编码的字符串,返回它解码后的字符串。
    编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
    你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
    此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。

    示例:
    输入:s = “3[a]2[bc]”
    输出:“aaabcbc”

    题解:定义一个string类型的链表,从前往后遍历字符串,首先定义一个方法得到多位数字的值,加入链表。当字符串中当前的值为"[“或者字母时,将其加入链表。定义一个子串,当目前值不为”[“时,将其加入字串,并且从链表中删除。然后该将字串反转,从链表中删除”["。定义一个stringbuffer,将反转后的字串重复数字次数加入stringbuffer,然后输出string。

    2.滑动窗口的最大值
    题目描述:
    给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。

    示例:
    输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
    输出: [3,3,5,5,6,7]
    解释:
    滑动窗口的位置 最大值


    [1 3 -1] -3 5 3 6 7 3
    1 [3 -1 -3] 5 3 6 7 3
    1 3 [-1 -3 5] 3 6 7 5
    1 3 -1 [-3 5 3] 6 7 5
    1 3 -1 -3 [5 3 6] 7 6
    1 3 -1 -3 5 [3 6 7] 7

    题解:
    滑动窗口,定义一个队列和一个整数数组。定义左边界i和有边界j。若对手元素等于被删除元素则队首元素出队。当队不为空且队尾的值小于当前要加入的值,则删除。加入当前值,输出当前队首到数组。

    3.最近的请求次数
    题目描述:
    写一个 RecentCounter 类来计算最近的请求。
    它只有一个方法:ping(int t),其中 t 代表以毫秒为单位的某个时间。
    返回从 3000 毫秒前到现在的 ping 数。
    任何处于 [t - 3000, t] 时间范围之内的 ping 都将会被计算在内,包括当前(指 t 时刻)的 ping。
    保证每次对 ping 的调用都使用比之前更大的 t 值。

    示例:
    输入:inputs = [“RecentCounter”,“ping”,“ping”,“ping”,“ping”], inputs = [[],[1],[100],[3001],[3002]]
    输出:[null,1,2,3,3]

    题解:

    4.任务调度器
    题目描述:
    给定一个用字符数组表示的 CPU 需要执行的任务列表。其中包含使用大写的 A - Z 字母表示的26 种不同种类的任务。任务可以以任意顺序执行,并且每个任务都可以在 1 个单位时间内执行完。CPU 在任何一个单位时间内都可以执行一个任务,或者在待命状态。
    然而,两个相同种类的任务之间必须有长度为 n 的冷却时间,因此至少有连续 n 个单位时间内 CPU 在执行不同的任务,或者在待命状态。
    你需要计算完成所有任务所需要的最短时间。

    示例:
    输入:tasks = [“A”,“A”,“A”,“B”,“B”,“B”], n = 2
    输出:8
    解释:A -> B -> (待命) -> A -> B -> (待命) -> A -> B.
    在本示例中,两个相同类型任务之间必须间隔长度为 n = 2 的冷却时间,而执行一个任务只需要一个单位时间,所以中间出现了(待命)状态。

    题解:
    定义一个数组保存26个字母的个数,定义一个优先队列,将其按个数多少从高到低排序。每次从高到底挑选n+1个字母,加入一个队列并计算时间,若其中的个数小于一,则将这个数移除,如果优先队列为空零时数组中的元素为零,则返回时间。

    5.第 k 个数
    题目描述:
    有些数的素因子只有 3,5,7,请设计一个算法找出第 k 个数。注意,不是必须有这些素因子,而是必须不包含其他的素因子。例如,前几个数按顺序应该是 1,3,5,7,9,15,21。

    示例:
    输入: k = 5
    输出: 9

    题解:
    定义一个优先队列,先加入1,定义一个hashset没有重复值。然后将队首元素加入hashset,将该值*3/*5/7分别加入优先队列。如果list的size==k,则返回该值。

    6.设计循环队列
    题目描述:
    设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
    循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。
    你的实现应该支持如下操作:
    MyCircularQueue(k): 构造器,设置队列长度为 k 。
    Front: 从队首获取元素。如果队列为空,返回 -1 。
    Rear: 获取队尾元素。如果队列为空,返回 -1 。
    enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
    deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
    isEmpty(): 检查循环队列是否为空。
    isFull(): 检查循环队列是否已满。

    示例:
    MyCircularQueue circularQueue = new MyCircularQueue(3); // 设置长度为
    circularQueue.enQueue(1); // 返回 true
    circularQueue.enQueue(2); // 返回 true
    circularQueue.enQueue(3); // 返回 true
    circularQueue.enQueue(4); // 返回 false,队列已满
    circularQueue.Rear(); // 返回 3
    circularQueue.isFull(); // 返回 true
    circularQueue.deQueue(); // 返回 true
    circularQueue.enQueue(4); // 返回 true
    circularQueue.Rear(); // 返回 4

    题解:

    7.设计循环双端队列
    题目描述:
    设计实现双端队列。
    你的实现需要支持以下操作:
    MyCircularDeque(k):构造函数,双端队列的大小为k。
    insertFront():将一个元素添加到双端队列头部。 如果操作成功返回 true。
    insertLast():将一个元素添加到双端队列尾部。如果操作成功返回 true。
    deleteFront():从双端队列头部删除一个元素。 如果操作成功返回 true。
    deleteLast():从双端队列尾部删除一个元素。如果操作成功返回 true。
    getFront():从双端队列头部获得一个元素。如果双端队列为空,返回 -1。
    getRear():获得双端队列的最后一个元素。 如果双端队列为空,返回 -1。
    isEmpty():检查双端队列是否为空。
    isFull():检查双端队列是否满了。

    示例:
    MyCircularDeque circularDeque = new MycircularDeque(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

    题解:
    每个节点不仅指向下一个节点也指向前一个结点。

    二.相关语法及用法
    LinkedList stk = new LinkedList();
    stk.addLast();
    stk.removeLast()
    PriorityQueue PriorityQueue = new PriorityQueue<>();

    cs