diff --git a/Contents/03.Stack/01.Stack-Basic/01.Stack-Basic.md b/Contents/03.Stack/01.Stack-Basic/01.Stack-Basic.md index c512b515..8c1b6e9c 100644 --- a/Contents/03.Stack/01.Stack-Basic/01.Stack-Basic.md +++ b/Contents/03.Stack/01.Stack-Basic/01.Stack-Basic.md @@ -185,28 +185,44 @@ class Stack: #### 3.1.2 题目大意 -给定一个只包括 `'('`,`')'`,`'{'`,`'}'`,`'['`,`']'` 的字符串 `s`。 +**描述**:给定一个只包括 `'('`,`')'`,`'{'`,`'}'`,`'['`,`']'` 的字符串 `s` 。 -要求:判断括号是否匹配。如果匹配,返回 `True`,否则返回 `False`。 +**要求**:判断字符串 `s` 是否有效(即括号是否匹配)。 + +**说明**: + +- 有效字符串需满足: + 1. 左括号必须用相同类型的右括号闭合。 + 2. 左括号必须以正确的顺序闭合。 + +**示例**: + +```Python +输入:s = "()" +输出:True + + +输入:s = "()[]{}" +输出:True +``` #### 3.2.3 解题思路 -括号匹配是「栈」的经典应用。 +##### 思路 1:栈 -我们可以用栈来解决这道题。具体做法如下: +括号匹配是「栈」的经典应用。我们可以用栈来解决这道题。具体做法如下: -- 先判断一下字符串的长度是否为偶数。因为括号是成对出现的,所以字符串的长度应为偶数,可以直接判断长度为奇数的字符串不匹配。 - - 如果字符串长度为奇数,则说明字符串 `s` 中的括号不匹配,直接返回 `False`。 -- 使用栈 `stack` 来保存未匹配的左括号。然后依次遍历字符串 `s` 中的每一个字符。 - - 如果遍历到左括号时,将其入栈。 - - 如果遍历到右括号时,先看栈顶元素是否是与当前右括号相同类型的左括号。 - - 如果是相同类型的左括号,则令其出栈,继续向前遍历。 - - 如果不是相同类型的左括号,则说明字符串 `s` 中的括号不匹配,直接返回 `False`。 -- 遍历完,再判断一下栈是否为空。 - - 如果栈为空,则说明字符串 `s` 中的括号匹配,返回 `True`。 - - 如果栈不为空,则说明字符串 `s` 中的括号不匹配,返回 `False`。 +1. 先判断一下字符串的长度是否为偶数。因为括号是成对出现的,所以字符串的长度应为偶数,可以直接判断长度为奇数的字符串不匹配。如果字符串长度为奇数,则说明字符串 `s` 中的括号不匹配,直接返回 `False`。 +2. 使用栈 `stack` 来保存未匹配的左括号。然后依次遍历字符串 `s` 中的每一个字符。 + 1. 如果遍历到左括号时,将其入栈。 + 2. 如果遍历到右括号时,先看栈顶元素是否是与当前右括号相同类型的左括号。 + 1. 如果是与当前右括号相同类型的左括号,则令其出栈,继续向前遍历。 + 2. 如果不是与当前右括号相同类型的左括号,则说明字符串 `s` 中的括号不匹配,直接返回 `False`。 +3. 遍历完,还要再判断一下栈是否为空。 + 1. 如果栈为空,则说明字符串 `s` 中的括号匹配,返回 `True`。 + 2. 如果栈不为空,则说明字符串 `s` 中的括号不匹配,返回 `False`。 -#### 3.2.4 代码 +##### 思路 1:代码 ```Python class Solution: @@ -238,6 +254,11 @@ class Solution: return False ``` +##### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n)$。 +- **空间复杂度**:$O(1)$。 + ### 3.2 表达式求值问题 #### 3.2.1 题目链接 @@ -246,30 +267,49 @@ class Solution: #### 3.2.2 题目大意 -给定一个字符串表达式 `s`,表达式中所有整数为非负整数,运算符只有 `+`、`-`、`*`、`/`,没有括号。 +**描述**:给定一个字符串表达式 `s`,表达式中所有整数为非负整数,运算符只有 `+`、`-`、`*`、`/`,没有括号。 -要求:实现一个基本计算器来计算并返回它的值。 +**要求**:实现一个基本计算器来计算并返回它的值。 + +**说明**: + +- 1ドル \le s.length \le 3 * 10^5$。 +- `s` 由整数和算符(`+`、`-`、`*`、`/`)组成,中间由一些空格隔开。 +- `s` 表示一个有效表达式。 +- 表达式中的所有整数都是非负整数,且在范围 $[0, 2^{31} - 1]$ 内。 +- 题目数据保证答案是一个 32-bit 整数。 + +**示例**: + +```Python +输入:s = "3+2*2" +输出:7 + + +输入:s = " 3/2 " +输出:1 +``` #### 3.2.3 解题思路 -表达式求值问题也是栈的经典应用。 +##### 思路 1:栈 -在计算表达式中,乘除运算优先于加减运算。我们可以先进行乘除运算,再将进行乘除运算后的整数值放入原表达式中相应位置,再依次计算加减。 +计算表达式中,乘除运算优先于加减运算。我们可以先进行乘除运算,再将进行乘除运算后的整数值放入原表达式中相应位置,再依次计算加减。 可以考虑使用一个栈来保存进行乘除运算后的整数值。正整数直接压入栈中,负整数,则将对应整数取负号,再压入栈中。这样最终计算结果就是栈中所有元素的和。 -具体做法如下: +具体做法: -- 遍历字符串 `s`,使用变量 `op` 来标记数字之前的运算符,默认为 `+`。 -- 如果遇到数字,继续向后遍历,将数字进行累积计算,得到完整的整数 `num`。判断当前 `op` 的符号。 - - 如果 op 为 `+`,则将 `num` 压入栈中。 - - 如果 op 为 `-`,则将 `-num` 压入栈中。 - - 如果 op 为 `*`,则将栈顶元素 `top` 取出,计算 `top * num`,并将计算结果压入栈中。 - - 如果 op 为 `/`,则将栈顶元素 `top` 取出,计算 `int(top / num)`,并将计算结果压入栈中。 -- 如果遇到 `+`、`-`、`*`、`/` 操作符,则更新 `op`。 -- 最后将栈中整数进行累加,并返回结果。 +1. 遍历字符串 `s`,使用变量 `op` 来标记数字之前的运算符,默认为 `+`。 +2. 如果遇到数字,继续向后遍历,将数字进行累积,得到完整的整数 num。判断当前 op 的符号。 + 1. 如果 `op` 为 `+`,则将 `num` 压入栈中。 + 2. 如果 `op` 为 `-`,则将 `-num` 压入栈中。 + 3. 如果 `op` 为 `*`,则将栈顶元素 `top` 取出,计算 `top * num`,并将计算结果压入栈中。 + 4. 如果 `op` 为 `/`,则将栈顶元素 `top` 取出,计算 `int(top / num)`,并将计算结果压入栈中。 +3. 如果遇到 `+`、`-`、`*`、`/` 操作符,则更新 `op`。 +4. 最后将栈中整数进行累加,并返回结果。 -#### 3.2.4 代码 +##### 思路 1:代码 ```Python class Solution: @@ -303,6 +343,11 @@ class Solution: return sum(stack) ``` +##### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n)$。 +- **空间复杂度**:$O(n)$。 + ## 参考资料 - 【书籍】数据结构与算法 Python 语言描述 - 裘宗燕 著 diff --git a/Contents/03.Stack/02.Monotone-Stack/01.Monotone-Stack.md b/Contents/03.Stack/02.Monotone-Stack/01.Monotone-Stack.md index 249a1943..c3b33c47 100644 --- a/Contents/03.Stack/02.Monotone-Stack/01.Monotone-Stack.md +++ b/Contents/03.Stack/02.Monotone-Stack/01.Monotone-Stack.md @@ -75,30 +75,48 @@ 所以单调栈一般用于解决一下几种问题: -- 寻找左侧第一个比当前元素大的元素 -- 寻找左侧第一个比当前元素小的元素 -- 寻找右侧第一个比当前元素大的元素 -- 寻找右侧第一个比当前元素小的元素 +- 寻找左侧第一个比当前元素大的元素。 +- 寻找左侧第一个比当前元素小的元素。 +- 寻找右侧第一个比当前元素大的元素。 +- 寻找右侧第一个比当前元素小的元素。 下面分别说一下这几种问题的求解方法。 ### 2.1 寻找左侧第一个比当前元素大的元素 -- 从左到右遍历元素,构造单调递增栈(从栈顶到栈底递增):一个元素左侧第一个比它大的元素就是将其「插入单调递增栈」时的栈顶元素。如果插入时的栈为空,则说明左侧不存在比当前元素大的元素。 +- 从左到右遍历元素,构造单调递增栈(从栈顶到栈底递增): + - 一个元素左侧第一个比它大的元素就是将其「插入单调递增栈」时的栈顶元素。 + - 如果插入时的栈为空,则说明左侧不存在比当前元素大的元素。 + ### 2.2 寻找左侧第一个比当前元素小的元素 -- 从左到右遍历元素,构造单调递减栈(从栈顶到栈底递减):一个元素左侧第一个比它小的元素就是将其「插入单调递减栈」时的栈顶元素。如果插入时的栈为空,则说明左侧不存在比当前元素小的元素。 +- 从左到右遍历元素,构造单调递减栈(从栈顶到栈底递减): + - 一个元素左侧第一个比它小的元素就是将其「插入单调递减栈」时的栈顶元素。 + - 如果插入时的栈为空,则说明左侧不存在比当前元素小的元素。 + ### 2.3 寻找右侧第一个比当前元素大的元素 -- 从左到右遍历元素,构造单调递增栈(从栈顶到栈底递增):一个元素右侧第一个比它大的元素就是将其「弹出单调递增栈」时即将插入的元素。如果该元素没有被弹出栈,则说明右侧不存在比当前元素大的元素。 -- 从右到左遍历元素,构造单调递增栈(从栈顶到栈底递增):一个元素右侧第一个比它大的元素就是将其「插入单调递增栈」时的栈顶元素。如果插入时的栈为空,则说明右侧不存在比当前元素大的元素。 +- 从左到右遍历元素,构造单调递增栈(从栈顶到栈底递增): + - 一个元素右侧第一个比它大的元素就是将其「弹出单调递增栈」时即将插入的元素。 + - 如果该元素没有被弹出栈,则说明右侧不存在比当前元素大的元素。 + +- 从右到左遍历元素,构造单调递增栈(从栈顶到栈底递增): + - 一个元素右侧第一个比它大的元素就是将其「插入单调递增栈」时的栈顶元素。 + - 如果插入时的栈为空,则说明右侧不存在比当前元素大的元素。 + ### 2.4 寻找右侧第一个比当前元素小的元素 -- 从左到右遍历元素,构造单调递减栈(从栈顶到栈底递减):一个元素右侧第一个比它小的元素就是将其「弹出单调递减栈」时即将插入的元素。如果该元素没有被弹出栈,则说明右侧不存在比当前元素小的元素。 -- 从右到左遍历元素,构造单调递减栈(从栈顶到栈底递减):一个元素右侧第一个比它小的元素就是将其「插入单调递减栈」时的栈顶元素。如果插入时的栈为空,则说明右侧不存在比当前元素小的元素。 +- 从左到右遍历元素,构造单调递减栈(从栈顶到栈底递减): + - 一个元素右侧第一个比它小的元素就是将其「弹出单调递减栈」时即将插入的元素。 + - 如果该元素没有被弹出栈,则说明右侧不存在比当前元素小的元素。 + +- 从右到左遍历元素,构造单调递减栈(从栈顶到栈底递减): + - 一个元素右侧第一个比它小的元素就是将其「插入单调递减栈」时的栈顶元素。 + - 如果插入时的栈为空,则说明右侧不存在比当前元素小的元素。 + 上边的分类解法有点绕口,可以简单记为以下条规则: @@ -192,9 +210,25 @@ class Solution: #### 4.2.2 题目大意 -给定一个列表 `temperatures`,每一个位置对应每天的气温。 +**描述**:给定一个列表 `temperatures`,`temperatures[i]` 表示第 `i` 天的气温。 + +**要求**:输出一个列表,列表上每个位置代表「如果要观测到更高的气温,至少需要等待的天数」。如果之后的气温不再升高,则用 `0` 来代替。 + +**说明**: + +- 1ドル \le temperatures.length \le 10^5$。 +- 30ドル \le temperatures[i] \le 100$。 -要求:输出一个列表,列表上每个位置代表如果要观测到更高的气温,至少需要等待的天数。如果之后的气温不再升高,则用 `0` 来代替。 +**示例**: + +```Python +输入: temperatures = [73,74,75,71,69,72,76,73] +输出: [1,1,4,2,1,1,0,0] + + +输入: temperatures = [30,40,50,60] +输出: [1,1,1,0] +``` #### 4.2.3 解题思路 @@ -202,16 +236,18 @@ class Solution: 最简单的思路是对于每个温度值,向后依次进行搜索,找到比当前温度更高的值。 -更好的方式使用「单调递增栈」。栈中保存元素的下标。 +更好的方式使用「单调递增栈」,栈中保存元素的下标。 + +##### 思路 1:单调栈 -- 首先,将答案数组 `ans` 全部赋值为 0。然后遍历数组每个位置元素。 -- 如果栈为空,则将当前元素的下标入栈。 -- 如果栈不为空,且当前数字大于栈顶元素对应数字,则栈顶元素出栈,并计算下标差。 - - 此时当前元素就是栈顶元素的下一个更高值,将其下标差存入答案数组 `ans` 中保存起来,判断栈顶元素。 -- 直到当前数字小于或等于栈顶元素,则停止出栈,将当前元素下标入栈。 -- 最后输出答案数组 `ans`。 +1. 首先,将答案数组 `ans` 全部赋值为 0。然后遍历数组每个位置元素。 +2. 如果栈为空,则将当前元素的下标入栈。 +3. 如果栈不为空,且当前数字大于栈顶元素对应数字,则栈顶元素出栈,并计算下标差。 +4. 此时当前元素就是栈顶元素的下一个更高值,将其下标差存入答案数组 `ans` 中保存起来,判断栈顶元素。 +5. 直到当前数字小于或等于栈顶元素,则停止出栈,将当前元素下标入栈。 +6. 最后输出答案数组 `ans`。 -#### 4.2.4 代码 +##### 思路 1:代码 ```Python class Solution: @@ -227,6 +263,11 @@ class Solution: return ans ``` +##### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n)$。 +- **空间复杂度**:$O(n)$。 + ## 参考资料 - 【博文】[动画:什么是单调栈?_- 吴师兄学编程](https://www.cxyxiaowu.com/450.html) diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 index 4bf38488..58ceff3d --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,350 @@ -MIT License - -Copyright (c) 2021 itcharge - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 +International + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright and +certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + +Considerations for licensors: Our public licenses are intended for use +by those authorized to give the public permission to use material in +ways otherwise restricted by copyright and certain other rights. Our +licenses are irrevocable. Licensors should read and understand the terms +and conditions of the license they choose before applying it. Licensors +should also secure all rights necessary before applying our licenses so +that the public can reuse the material as expected. Licensors should +clearly mark any material not subject to the license. This includes +other CC-licensed material, or material used under an exception or +limitation to copyright. More considerations for licensors : +wiki.creativecommons.org/Considerations_for_licensors + +Considerations for the public: By using one of our public licenses, a +licensor grants the public permission to use the licensed material under +specified terms and conditions. If the licensor's permission is not +necessary for any reason–for example, because of any applicable +exception or limitation to copyright–then that use is not regulated by +the license. Our licenses grant only permissions under copyright and +certain other rights that a licensor has authority to grant. Use of the +licensed material may still be restricted for other reasons, including +because others have copyright or other rights in the material. A +licensor may make special requests, such as asking that all changes be +marked or described. Although not required by our licenses, you are +encouraged to respect those requests where reasonable. More +considerations for the public : +wiki.creativecommons.org/Considerations_for_licensees + +Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 +International Public License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-NonCommercial-NoDerivatives 4.0 International Public License +("Public License"). To the extent this Public License may be interpreted +as a contract, You are granted the Licensed Rights in consideration of +Your acceptance of these terms and conditions, and the Licensor grants +You such rights in consideration of benefits the Licensor receives from +making the Licensed Material available under these terms and conditions. + +- Section 1 – Definitions. + + - a. Adapted Material means material subject to Copyright and + Similar Rights that is derived from or based upon the Licensed + Material and in which the Licensed Material is translated, + altered, arranged, transformed, or otherwise modified in a + manner requiring permission under the Copyright and Similar + Rights held by the Licensor. For purposes of this Public + License, where the Licensed Material is a musical work, + performance, or sound recording, Adapted Material is always + produced where the Licensed Material is synched in timed + relation with a moving image. + - b. Copyright and Similar Rights means copyright and/or similar + rights closely related to copyright including, without + limitation, performance, broadcast, sound recording, and Sui + Generis Database Rights, without regard to how the rights are + labeled or categorized. For purposes of this Public License, the + rights specified in Section 2(b)(1)-(2) are not Copyright and + Similar Rights. + - c. Effective Technological Measures means those measures that, + in the absence of proper authority, may not be circumvented + under laws fulfilling obligations under Article 11 of the WIPO + Copyright Treaty adopted on December 20, 1996, and/or similar + international agreements. + - d. Exceptions and Limitations means fair use, fair dealing, + and/or any other exception or limitation to Copyright and + Similar Rights that applies to Your use of the Licensed + Material. + - e. Licensed Material means the artistic or literary work, + database, or other material to which the Licensor applied this + Public License. + - f. Licensed Rights means the rights granted to You subject to + the terms and conditions of this Public License, which are + limited to all Copyright and Similar Rights that apply to Your + use of the Licensed Material and that the Licensor has authority + to license. + - g. Licensor means the individual(s) or entity(ies) granting + rights under this Public License. + - h. NonCommercial means not primarily intended for or directed + towards commercial advantage or monetary compensation. For + purposes of this Public License, the exchange of the Licensed + Material for other material subject to Copyright and Similar + Rights by digital file-sharing or similar means is NonCommercial + provided there is no payment of monetary compensation in + connection with the exchange. + - i. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, + distribution, dissemination, communication, or importation, and + to make material available to the public including in ways that + members of the public may access the material from a place and + at a time individually chosen by them. + - j. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and + of the Council of 11 March 1996 on the legal protection of + databases, as amended and/or succeeded, as well as other + essentially equivalent rights anywhere in the world. + - k. You means the individual or entity exercising the Licensed + Rights under this Public License. Your has a corresponding + meaning. + +- Section 2 – Scope. + + - a. License grant. + - 1. Subject to the terms and conditions of this Public + License, the Licensor hereby grants You a worldwide, + royalty-free, non-sublicensable, non-exclusive, irrevocable + license to exercise the Licensed Rights in the Licensed + Material to: + - A. reproduce and Share the Licensed Material, in whole + or in part, for NonCommercial purposes only; and + - B. produce and reproduce, but not Share, Adapted + Material for NonCommercial purposes only. + - 2. Exceptions and Limitations. For the avoidance of doubt, + where Exceptions and Limitations apply to Your use, this + Public License does not apply, and You do not need to comply + with its terms and conditions. + - 3. Term. The term of this Public License is specified in + Section 6(a). + - 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter + created, and to make technical modifications necessary to do + so. The Licensor waives and/or agrees not to assert any + right or authority to forbid You from making technical + modifications necessary to exercise the Licensed Rights, + including technical modifications necessary to circumvent + Effective Technological Measures. For purposes of this + Public License, simply making modifications authorized by + this Section 2(a)(4) never produces Adapted Material. + - 5. Downstream recipients. + - A. Offer from the Licensor – Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + - B. No downstream restrictions. You may not offer or + impose any additional or different terms or conditions + on, or apply any Effective Technological Measures to, + the Licensed Material if doing so restricts exercise of + the Licensed Rights by any recipient of the Licensed + Material. + - 6. No endorsement. Nothing in this Public License + constitutes or may be construed as permission to assert or + imply that You are, or that Your use of the Licensed + Material is, connected with, or sponsored, endorsed, or + granted official status by, the Licensor or others + designated to receive attribution as provided in Section + 3(a)(1)(A)(i). + - b. Other rights. + - 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, + to the extent possible, the Licensor waives and/or agrees + not to assert any such rights held by the Licensor to the + limited extent necessary to allow You to exercise the + Licensed Rights, but not otherwise. + - 2. Patent and trademark rights are not licensed under this + Public License. + - 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties, including when + the Licensed Material is used other than for NonCommercial + purposes. + +- Section 3 – License Conditions. + + Your exercise of the Licensed Rights is expressly made subject to + the following conditions. + + - a. Attribution. + - 1. If You Share the Licensed Material, You must: + + - A. retain the following if it is supplied by the + Licensor with the Licensed Material: + - i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if designated); + - ii. a copyright notice; + - iii. a notice that refers to this Public License; + - iv. a notice that refers to the disclaimer of + warranties; + - v. a URI or hyperlink to the Licensed Material to + the extent reasonably practicable; + - B. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + - C. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + For the avoidance of doubt, You do not have permission under + this Public License to Share Adapted Material. + + - 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may + be reasonable to satisfy the conditions by providing a URI + or hyperlink to a resource that includes the required + information. + - 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + +- Section 4 – Sui Generis Database Rights. + + Where the Licensed Rights include Sui Generis Database Rights that + apply to Your use of the Licensed Material: + + - a. for the avoidance of doubt, Section 2(a)(1) grants You the + right to extract, reuse, reproduce, and Share all or a + substantial portion of the contents of the database for + NonCommercial purposes only and provided You do not Share + Adapted Material; + - b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material; + and + - c. You must comply with the conditions in Section 3(a) if You + Share all or a substantial portion of the contents of the + database. + + For the avoidance of doubt, this Section 4 supplements and does not + replace Your obligations under this Public License where the + Licensed Rights include other Copyright and Similar Rights. + +- Section 5 – Disclaimer of Warranties and Limitation of Liability. + + - a. Unless otherwise separately undertaken by the Licensor, to + the extent possible, the Licensor offers the Licensed Material + as-is and as-available, and makes no representations or + warranties of any kind concerning the Licensed Material, whether + express, implied, statutory, or other. This includes, without + limitation, warranties of title, merchantability, fitness for a + particular purpose, non-infringement, absence of latent or other + defects, accuracy, or the presence or absence of errors, whether + or not known or discoverable. Where disclaimers of warranties + are not allowed in full or in part, this disclaimer may not + apply to You. + - b. To the extent possible, in no event will the Licensor be + liable to You on any legal theory (including, without + limitation, negligence) or otherwise for any direct, special, + indirect, incidental, consequential, punitive, exemplary, or + other losses, costs, expenses, or damages arising out of this + Public License or use of the Licensed Material, even if the + Licensor has been advised of the possibility of such losses, + costs, expenses, or damages. Where a limitation of liability is + not allowed in full or in part, this limitation may not apply to + You. + - c. The disclaimer of warranties and limitation of liability + provided above shall be interpreted in a manner that, to the + extent possible, most closely approximates an absolute + disclaimer and waiver of all liability. + +- Section 6 – Term and Termination. + + - a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply + with this Public License, then Your rights under this Public + License terminate automatically. + - b. Where Your right to use the Licensed Material has terminated + under Section 6(a), it reinstates: + + - 1. automatically as of the date the violation is cured, + provided it is cured within 30 days of Your discovery of the + violation; or + - 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect + any right the Licensor may have to seek remedies for Your + violations of this Public License. + + - c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing + so will not terminate this Public License. + - d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + +- Section 7 – Other Terms and Conditions. + + - a. The Licensor shall not be bound by any additional or + different terms or conditions communicated by You unless + expressly agreed. + - b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + +- Section 8 – Interpretation. + + - a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could + lawfully be made without permission under this Public License. + - b. To the extent possible, if any provision of this Public + License is deemed unenforceable, it shall be automatically + reformed to the minimum extent necessary to make it enforceable. + If the provision cannot be reformed, it shall be severed from + this Public License without affecting the enforceability of the + remaining terms and conditions. + - c. No term or condition of this Public License will be waived + and no failure to comply consented to unless expressly agreed to + by the Licensor. + - d. Nothing in this Public License constitutes or may be + interpreted as a limitation upon, or waiver of, any privileges + and immunities that apply to the Licensor or You, including from + the legal processes of any jurisdiction or authority. + +Creative Commons is not a party to its public licenses. Notwithstanding, +Creative Commons may elect to apply one of its public licenses to +material it publishes and in those instances will be considered the +"Licensor." The text of the Creative Commons public licenses is +dedicated to the public domain under the CC0 Public Domain Dedication. +Except for the limited purpose of indicating that material is shared +under a Creative Commons public license or as otherwise permitted by the +Creative Commons policies published at creativecommons.org/policies, +Creative Commons does not authorize the use of the trademark "Creative +Commons" or any other trademark or logo of Creative Commons without its +prior written consent including, without limitation, in connection with +any unauthorized modifications to any of its public licenses or any +other arrangements, understandings, or agreements concerning use of +licensed material. For the avoidance of doubt, this paragraph does not +form part of the public licenses. + +Creative Commons may be contacted at creativecommons.org. \ No newline at end of file diff --git "a/Solutions/0020. 346円234円211円346円225円210円347円232円204円346円213円254円345円217円267円.md" "b/Solutions/0020. 346円234円211円346円225円210円347円232円204円346円213円254円345円217円267円.md" index a00bc010..1cc36e93 100644 --- "a/Solutions/0020. 346円234円211円346円225円210円347円232円204円346円213円254円345円217円267円.md" +++ "b/Solutions/0020. 346円234円211円346円225円210円347円232円204円346円213円254円345円217円267円.md" @@ -5,28 +5,44 @@ ## 题目大意 -给定一个只包括 `'('`,`')'`,`'{'`,`'}'`,`'['`,`']'` 的字符串 `s` 。 +**描述**:给定一个只包括 `'('`,`')'`,`'{'`,`'}'`,`'['`,`']'` 的字符串 `s` 。 -要求:判断括号是否匹配。 +**要求**:判断字符串 `s` 是否有效(即括号是否匹配)。 + +**说明**: + +- 有效字符串需满足: + 1. 左括号必须用相同类型的右括号闭合。 + 2. 左括号必须以正确的顺序闭合。 + +**示例**: + +```Python +输入:s = "()" +输出:True + + +输入:s = "()[]{}" +输出:True +``` ## 解题思路 -括号匹配是「栈」的经典应用。 +### 思路 1:栈 -我们可以用栈来解决这道题。具体做法如下: +括号匹配是「栈」的经典应用。我们可以用栈来解决这道题。具体做法如下: -- 先判断一下字符串的长度是否为偶数。因为括号是成对出现的,所以字符串的长度应为偶数,可以直接判断长度为奇数的字符串不匹配。 - - 如果字符串长度为奇数,则说明字符串 `s` 中的括号不匹配,直接返回 `False`。 -- 使用栈 `stack` 来保存未匹配的左括号。然后依次遍历字符串 `s` 中的每一个字符。 - - 如果遍历到左括号时,将其入栈。 - - 如果遍历到右括号时,先看栈顶元素是否是与当前右括号相同类型的左括号。 - - 如果是相同类型的左括号,则令其出栈,继续向前遍历。 - - 如果不是相同类型的左括号,则说明字符串 `s` 中的括号不匹配,直接返回 `False`。 -- 遍历完,还要再判断一下栈是否为空。 - - 如果栈为空,则说明字符串 `s` 中的括号匹配,返回 `True`。 - - 如果栈不为空,则说明字符串 `s` 中的括号不匹配,返回 `False`。 +1. 先判断一下字符串的长度是否为偶数。因为括号是成对出现的,所以字符串的长度应为偶数,可以直接判断长度为奇数的字符串不匹配。如果字符串长度为奇数,则说明字符串 `s` 中的括号不匹配,直接返回 `False`。 +2. 使用栈 `stack` 来保存未匹配的左括号。然后依次遍历字符串 `s` 中的每一个字符。 + 1. 如果遍历到左括号时,将其入栈。 + 2. 如果遍历到右括号时,先看栈顶元素是否是与当前右括号相同类型的左括号。 + 1. 如果是与当前右括号相同类型的左括号,则令其出栈,继续向前遍历。 + 2. 如果不是与当前右括号相同类型的左括号,则说明字符串 `s` 中的括号不匹配,直接返回 `False`。 +3. 遍历完,还要再判断一下栈是否为空。 + 1. 如果栈为空,则说明字符串 `s` 中的括号匹配,返回 `True`。 + 2. 如果栈不为空,则说明字符串 `s` 中的括号不匹配,返回 `False`。 -## 代码 +### 思路 1:代码 ```Python class Solution: @@ -58,3 +74,8 @@ class Solution: return False ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n)$。 +- **空间复杂度**:$O(n)$。 + diff --git "a/Solutions/0150. 351円200円206円346円263円242円345円205円260円350円241円250円350円276円276円345円274円217円346円261円202円345円200円274円.md" "b/Solutions/0150. 351円200円206円346円263円242円345円205円260円350円241円250円350円276円276円345円274円217円346円261円202円345円200円274円.md" index b021a639..bb51edfe 100644 --- "a/Solutions/0150. 351円200円206円346円263円242円345円205円260円350円241円250円350円276円276円345円274円217円346円261円202円345円200円274円.md" +++ "b/Solutions/0150. 351円200円206円346円263円242円345円205円260円350円241円250円350円276円276円345円274円217円346円261円202円345円200円274円.md" @@ -5,12 +5,42 @@ ## 题目大意 -给定一个字符串数组,表示「逆波兰表达式」。 +**描述**:给定一个字符串数组 `tokens`,表示「逆波兰表达式」。 -要求:求解表达式的值。 +**要求**:求解表达式的值。 + +**说明**: + +- **逆波兰表达式**:也称为后缀表达式。 + - 中缀表达式 `( 1 + 2 ) * ( 3 + 4 ) `,对应的逆波兰表达式为 ` ( ( 1 2 + ) ( 3 4 + ) * )` 。 + +- 1ドル \le tokens.length \le 10^4$。 +- `tokens[i]` 是一个算符(`+`、`-`、`*` 或 `/`),或是在范围 $[-200, 200]$ 内的一个整数。 + +**示例**: + +```Python +输入:tokens = ["4","13","5","/","+"] +输出:6 +解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6 + + +输入: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:栈 + 这道题是栈的典型应用。我们先来简单介绍一下逆波兰表达式。 逆波兰表达式,也叫做后缀表达式,特点是:没有括号,运算符总是放在和它相关的操作数之后。 @@ -19,12 +49,12 @@ 逆波兰表达式的计算遵循从左到右的规律。我们在计算逆波兰表达式的值时,可以使用一个栈来存放当前的操作数,从左到右依次遍历逆波兰表达式,计算出对应的值。具体操作步骤如下: -- 使用列表 `stack` 作为栈存放操作数,然后遍历表达式的字符串数组。 -- 如果当前字符为运算符,则取出栈顶两个元素,在进行对应的运算之后,再将运算结果入栈。 -- 如果当前字符为数字,则直接将数字入栈。 -- 遍历结束后弹出栈中最后剩余的元素,这就是最终结果。 +1. 使用列表 `stack` 作为栈存放操作数,然后遍历表达式的字符串数组。 +2. 如果当前字符为运算符,则取出栈顶两个元素,在进行对应的运算之后,再将运算结果入栈。 +3. 如果当前字符为数字,则直接将数字入栈。 +4. 遍历结束后弹出栈中最后剩余的元素,这就是最终结果。 -## 代码 +### 思路 1:代码 ```Python class Solution: @@ -38,8 +68,13 @@ class Solution: elif token == '*': stack.append(stack.pop() * stack.pop()) elif token == '/': - stack.append(int(1/stack.pop()*stack.pop())) + stack.append(int(1 / stack.pop() * stack.pop())) else: stack.append(int(token)) return stack.pop() ``` + +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n)$。 +- **空间复杂度**:$O(n)$。 diff --git "a/Solutions/0155. 346円234円200円345円260円217円346円240円210円.md" "b/Solutions/0155. 346円234円200円345円260円217円346円240円210円.md" index 904d97b2..12938939 100644 --- "a/Solutions/0155. 346円234円200円345円260円217円346円240円210円.md" +++ "b/Solutions/0155. 346円234円200円345円260円217円346円240円210円.md" @@ -5,31 +5,49 @@ ## 题目大意 -要求:设计一个「栈」。实现 `push` ,`pop` ,`top` ,`getMin` 操作,其中 `getMin` 要求能在常数时间内实现。 +**要求**:设计一个「栈」。实现 `push` ,`pop` ,`top` ,`getMin` 操作,其中 `getMin` 要求能在常数时间内实现。 + +**说明**: + +- $-2^{31} \le val \le 2^{31} - 1$。 +- `pop`、`top` 和 `getMin` 操作总是在非空栈上调用 +- `push`,`pop`,`top` 和 `getMin` 最多被调用 3ドル * 10^4$ 次。 + +**示例**: + +```Python +输入: +["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. +``` ## 解题思路 -题目要求在常数时间内获取最小值,所以我们不能在 `getMin` 操作时,再去计算栈中的最小值。而是应该在 `push`、`pop` 操作时就已经计算好了最小值。 +题目要求在常数时间内获取最小值,所以我们不能在 `getMin` 操作时,再去计算栈中的最小值。而是应该在 `push`、`pop` 操作时就已经计算好了最小值。我们有两种思路来解决这道题。 -我们有两种思路来解决这道题。 +### 思路 1:辅助栈 -思路一:使用辅助栈保存当前栈中的最小值。在元素入栈出栈时,两个栈同步保持插入和删除。具体做法如下: +使用辅助栈保存当前栈中的最小值。在元素入栈出栈时,两个栈同步保持插入和删除。具体做法如下: - `push` 操作:当一个元素入栈时,取辅助栈的栈顶存储的最小值,与当前元素进行比较得出最小值,将最小值插入到辅助栈中;该元素也插入到正常栈中。 - `pop` 操作:当一个元素要出栈时,将辅助栈的栈顶元素一起弹出。 - `top` 操作:返回正常栈的栈顶元素值。 - `getMin` 操作:返回辅助栈的栈顶元素值。 -思路二:使用一个栈,保存元组:(当前元素值,当前栈内最小值)。具体操作如下: - -- `push` 操作:如果栈不为空,则判断当前元素值与栈顶元素所保存的最小值,并更新当前最小值,然后将新元素和当前最小值组成的元组保存到栈中。 -- `pop`操作:正常出栈,即将栈顶元素弹出。 -- `top` 操作:返回栈顶元素保存的值。 -- `getMin` 操作:返回栈顶元素保存的最小值。 - -## 代码 - -- 思路一: +### 思路 1:代码 ```Python class MinStack: @@ -57,7 +75,21 @@ class MinStack: return self.minstack[-1] ``` -- 思路二: +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(1)$。栈的插入、删除、读取操作都是 $O(1)$。 +- **空间复杂度**:$O(n)$。其中 $n$ 为总操作数。 + +### 思路 2:单个栈 + +使用单个栈,保存元组:(当前元素值,当前栈内最小值)。具体操作如下: + +- `push` 操作:如果栈不为空,则判断当前元素值与栈顶元素所保存的最小值,并更新当前最小值,然后将新元素和当前最小值组成的元组保存到栈中。 +- `pop`操作:正常出栈,即将栈顶元素弹出。 +- `top` 操作:返回栈顶元素保存的值。 +- `getMin` 操作:返回栈顶元素保存的最小值。 + +### 思路 2:代码 ```Python class MinStack: @@ -93,3 +125,7 @@ class MinStack: return self.stack[-1].min ``` +### 思路 2:复杂度分析 + +- **时间复杂度**:$O(1)$。栈的插入、删除、读取操作都是 $O(1)$。 +- **空间复杂度**:$O(n)$。其中 $n$ 为总操作数。 \ No newline at end of file diff --git "a/Solutions/0227. 345円237円272円346円234円254円350円256円241円347円256円227円345円231円250円 II.md" "b/Solutions/0227. 345円237円272円346円234円254円350円256円241円347円256円227円345円231円250円 II.md" index 82738f80..653bc5ab 100644 --- "a/Solutions/0227. 345円237円272円346円234円254円350円256円241円347円256円227円345円231円250円 II.md" +++ "b/Solutions/0227. 345円237円272円346円234円254円350円256円241円347円256円227円345円231円250円 II.md" @@ -5,28 +5,49 @@ ## 题目大意 -给定一个字符串表达式 `s`,表达式中所有整数为非负整数,运算符只有 `+`、`-`、`*`、`/`,没有括号。 +**描述**:给定一个字符串表达式 `s`,表达式中所有整数为非负整数,运算符只有 `+`、`-`、`*`、`/`,没有括号。 -要求:实现一个基本计算器来计算并返回它的值。 +**要求**:实现一个基本计算器来计算并返回它的值。 + +**说明**: + +- 1ドル \le s.length \le 3 * 10^5$。 +- `s` 由整数和算符(`+`、`-`、`*`、`/`)组成,中间由一些空格隔开。 +- `s` 表示一个有效表达式。 +- 表达式中的所有整数都是非负整数,且在范围 $[0, 2^{31} - 1]$ 内。 +- 题目数据保证答案是一个 32-bit 整数。 + +**示例**: + +```Python +输入:s = "3+2*2" +输出:7 + + +输入:s = " 3/2 " +输出:1 +``` ## 解题思路 +### 思路 1:栈 + 计算表达式中,乘除运算优先于加减运算。我们可以先进行乘除运算,再将进行乘除运算后的整数值放入原表达式中相应位置,再依次计算加减。 可以考虑使用一个栈来保存进行乘除运算后的整数值。正整数直接压入栈中,负整数,则将对应整数取负号,再压入栈中。这样最终计算结果就是栈中所有元素的和。 具体做法: -- 遍历字符串 `s`,使用变量 `op` 来标记数字之前的运算符,默认为 `+`。 -- 如果遇到数字,继续向后遍历,将数字进行累积,得到完整的整数 num。判断当前 op 的符号。 - - 如果 `op` 为 `+`,则将 `num` 压入栈中。 - - 如果 `op` 为 `-`,则将 `-num` 压入栈中。 - - 如果 `op` 为 `*`,则将栈顶元素 `top` 取出,计算 `top * num`,并将计算结果压入栈中。 - - 如果 `op` 为 `/`,则将栈顶元素 `top` 取出,计算 `int(top / num)`,并将计算结果压入栈中。 -- 如果遇到 `+`、`-`、`*`、`/` 操作符,则更新 `op`。 -- 最后将栈中整数进行累加,并返回结果。 +1. 遍历字符串 `s`,使用变量 `op` 来标记数字之前的运算符,默认为 `+`。 +2. 如果遇到数字,继续向后遍历,将数字进行累积,得到完整的整数 num。判断当前 op 的符号。 + 1. 如果 `op` 为 `+`,则将 `num` 压入栈中。 + 2. 如果 `op` 为 `-`,则将 `-num` 压入栈中。 + 3. 如果 `op` 为 `*`,则将栈顶元素 `top` 取出,计算 `top * num`,并将计算结果压入栈中。 + 4. 如果 `op` 为 `/`,则将栈顶元素 `top` 取出,计算 `int(top / num)`,并将计算结果压入栈中。 +3. 如果遇到 `+`、`-`、`*`、`/` 操作符,则更新 `op`。 +4. 最后将栈中整数进行累加,并返回结果。 -## 代码 +### 思路 1:代码 ```Python class Solution: @@ -60,3 +81,8 @@ class Solution: return sum(stack) ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n)$。 +- **空间复杂度**:$O(n)$。 + diff --git "a/Solutions/0316. 345円216円273円351円231円244円351円207円215円345円244円215円345円255円227円346円257円215円.md" "b/Solutions/0316. 345円216円273円351円231円244円351円207円215円345円244円215円345円255円227円346円257円215円.md" index 629d3c92..5900c626 100644 --- "a/Solutions/0316. 345円216円273円351円231円244円351円207円215円345円244円215円345円255円227円346円257円215円.md" +++ "b/Solutions/0316. 345円216円273円351円231円244円351円207円215円345円244円215円345円255円227円346円257円215円.md" @@ -5,32 +5,50 @@ ## 题目大意 -给定一个字符串 `s`。 +**描述**:给定一个字符串 `s`。 -要求:去除字符串中重复的字母,使得每个字母只出现一次。需要保证 **「返回结果的字典序最小(要求不能打乱其他字符的相对位置)」**。 +**要求**:去除字符串中重复的字母,使得每个字母只出现一次。需要保证 **「返回结果的字典序最小(要求不能打乱其他字符的相对位置)」**。 + +**说明**: + +- 1ドル \le s.length \le 10^4$。 +- `s` 由小写英文字母组成。 + +**示例**: + +```Python +输入:s = "bcabc" +输出:"abc" + + +输入:s = "cbacdcbc" +输出:"acdb" +``` ## 解题思路 +### 思路 1:哈希表 + 单调栈 + 针对题目的三个要求:去重、不能打乱其他字符顺序、字典序最小。我们来一一分析。 -1. 去重:可以通过 **「使用哈希表存储字母出现次数」** 的方式,将每个字母出现的次数统计起来,再遍历一遍,去除重复的字母。 -2. 不能打乱其他字符顺序:按顺序遍历,将非重复的字母存储到答案数组或者栈中,最后再拼接起来,就能保证不打乱其他字符顺序。 -3. 字典序最小:意味着字典序小的字母应该尽可能放在前面。 - - 对于第 `i` 个字符 `s[i]` 而言,如果第 `0` ~ `i - 1` 之间的某个字符 `s[j]` 在 `s[i]` 之后不再出现了,那么 `s[j]` 必须放到 `s[i]` 之前。 - - 而如果 `s[j]` 在之后还会出现,并且 `s[j]` 的字典序大于 `s[i]`,我们则可以先舍弃 `s[j]`,把 `s[i]` 尽可能的放到前面。后边再考虑使用 `s[j]` 所对应的字符。 +1. **去重**:可以通过 **「使用哈希表存储字母出现次数」** 的方式,将每个字母出现的次数统计起来,再遍历一遍,去除重复的字母。 +2. **不能打乱其他字符顺序**:按顺序遍历,将非重复的字母存储到答案数组或者栈中,最后再拼接起来,就能保证不打乱其他字符顺序。 +3. **字典序最小**:意味着字典序小的字母应该尽可能放在前面。 + 1. 对于第 `i` 个字符 `s[i]` 而言,如果第 `0` ~ `i - 1` 之间的某个字符 `s[j]` 在 `s[i]` 之后不再出现了,那么 `s[j]` 必须放到 `s[i]` 之前。 + 2. 而如果 `s[j]` 在之后还会出现,并且 `s[j]` 的字典序大于 `s[i]`,我们则可以先舍弃 `s[j]`,把 `s[i]` 尽可能的放到前面。后边再考虑使用 `s[j]` 所对应的字符。 -要满足第 3 条需求,我们可以使用 **「单调栈」** 来解决。我们使用单调栈存储 `s[i]` 之前出现的非重复、并且字典序最小的字符序列。整个算法步骤如下: -- 先遍历一遍字符串,用哈希表 `letter_counts` 统计出每个字母出现的次数。 -- 然后使用单调递减栈保存当前字符之前出现的非重复、并且字典序最小的字符序列。 +要满足第 3 条需求,我们可以使用 **「单调栈」** 来解决。我们使用单调栈存储 `s[i]` 之前出现的非重复、并且字典序最小的字符序列。整个算法步骤如下: -- 当遍历到 `s[i]` 时,如果 `s[i]` 没有在栈中出现过: - - 则比较 `s[i]` 和栈顶元素 `stack[-1]` 的字典序。如果 `s[i]` 的字典序小于栈顶元素 `stack[-1]`,并且栈顶元素之后的出现次数大于 `0`,则将栈顶元素弹出。 - - 然后继续判断 `s[i]` 和栈顶元素 `stack[-1]`,并且知道栈顶元素出现次数为 `0` 时停止弹出。此时将 `s[i]` 添加到单调栈中。 -- 从哈希表 `letter_counts` 中减去 `s[i]` 出现的次数,继续遍历。 -- 最后将单调栈中的字符依次拼接为答案字符串,并返回。 +1. 先遍历一遍字符串,用哈希表 `letter_counts` 统计出每个字母出现的次数。 +2. 然后使用单调递减栈保存当前字符之前出现的非重复、并且字典序最小的字符序列。 +3. 当遍历到 `s[i]` 时,如果 `s[i]` 没有在栈中出现过: + 1. 比较 `s[i]` 和栈顶元素 `stack[-1]` 的字典序。如果 `s[i]` 的字典序小于栈顶元素 `stack[-1]`,并且栈顶元素之后的出现次数大于 `0`,则将栈顶元素弹出。 + 2. 然后继续判断 `s[i]` 和栈顶元素 `stack[-1]`,并且知道栈顶元素出现次数为 `0` 时停止弹出。此时将 `s[i]` 添加到单调栈中。 +4. 从哈希表 `letter_counts` 中减去 `s[i]` 出现的次数,继续遍历。 +5. 最后将单调栈中的字符依次拼接为答案字符串,并返回。 -## 代码 +### 思路 1:代码 ```Python class Solution: @@ -53,6 +71,11 @@ class Solution: return ''.join(stack) ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n)$。 +- **空间复杂度**:$O(|\sum|),ドル其中 $\sum$ 为字符集合,$|\sum|$ 为字符种类个数。由于栈中字符不能重复,因此栈中最多有 $|\sum|$ 个字符。 + ## 参考资料 - 【题解】[去除重复数组 - 去除重复字母 - 力扣(LeetCode)](https://leetcode.cn/problems/remove-duplicate-letters/solution/qu-chu-zhong-fu-shu-zu-by-lu-shi-zhe-sokp/) diff --git "a/Solutions/0394. 345円255円227円347円254円246円344円270円262円350円247円243円347円240円201円.md" "b/Solutions/0394. 345円255円227円347円254円246円344円270円262円350円247円243円347円240円201円.md" index 7d552312..ba7479f1 100644 --- "a/Solutions/0394. 345円255円227円347円254円246円344円270円262円350円247円243円347円240円201円.md" +++ "b/Solutions/0394. 345円255円227円347円254円246円344円270円262円350円247円243円347円240円201円.md" @@ -5,22 +5,43 @@ ## 题目大意 -给定一个经过编码的字符串 `s`。 +**描述**:给定一个经过编码的字符串 `s`。 -要求:返回 `s` 经过解码之后的字符串。 +**要求**:返回 `s` 经过解码之后的字符串。 + +**说明**: - 编码规则:`k[encoded_string]`。`encoded_string` 为字符串,`k` 为整数。表示字符串 `encoded_string` 重复 `k` 次。 +- 1ドル \le s.length \le 30$。 +- `s` 由小写英文字母、数字和方括号 `[]` 组成。 +- `s` 保证是一个有效的输入。 +- `s` 中所有整数的取值范围为 $[1, 300]$。 + +**示例**: + +```Python +输入:s = "3[a]2[bc]" +输出:"aaabcbc" + + +输入:s = "3[a2[c]]" +输出:"accaccacc" +``` ## 解题思路 -使用两个栈 `stack1`、`stack2`。`stack1` 用来保存左括号前已经解码的字符串,`stack2` 用来存储左括号前的数字。再用 `res` 存储待解码的字符串、`num` 存储当前数字。然后遍历字符串。 +### 思路 1:栈 -- 如果遇到数字,则累加数字到 `num`。 -- 如果遇到左括号,将当前待解码字符串入栈 `stack1`,当前数字入栈 `stack2`,然后将 `res`、`nums` 清空。 -- 如果遇到右括号,则从 `stack1` 的取出待解码字符串 `res`,从 `stack2` 中取出当前数字 `num`,将其解码拼合成字符串赋值给 `res`。 -- 如果遇到其他情况(遇到字母),则将当前字母加入 `res` 中。 +1. 使用两个栈 `stack1`、`stack2`。`stack1` 用来保存左括号前已经解码的字符串,`stack2` 用来存储左括号前的数字。 +2. 用 `res` 存储待解码的字符串、`num` 存储当前数字。 +3. 遍历字符串。 + 1. 如果遇到数字,则累加数字到 `num`。 + 2. 如果遇到左括号,将当前待解码字符串入栈 `stack1`,当前数字入栈 `stack2`,然后将 `res`、`nums` 清空。 + 3. 如果遇到右括号,则从 `stack1` 的取出待解码字符串 `res`,从 `stack2` 中取出当前数字 `num`,将其解码拼合成字符串赋值给 `res`。 + 4. 如果遇到其他情况(遇到字母),则将当前字母加入 `res` 中。 +4. 遍历完输出解码之后的字符串 `res`。 -## 代码 +### 思路 1:代码 ```Python class Solution: @@ -46,3 +67,8 @@ class Solution: return res ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n)$。 +- **空间复杂度**:$O(n)$。 + diff --git "a/Solutions/0496. 344円270円213円344円270円200円344円270円252円346円233円264円345円244円247円345円205円203円347円264円240円 I.md" "b/Solutions/0496. 344円270円213円344円270円200円344円270円252円346円233円264円345円244円247円345円205円203円347円264円240円 I.md" index 0f39d1d1..93e5792c 100644 --- "a/Solutions/0496. 344円270円213円344円270円200円344円270円252円346円233円264円345円244円247円345円205円203円347円264円240円 I.md" +++ "b/Solutions/0496. 344円270円213円344円270円200円344円270円252円346円233円264円345円244円247円345円205円203円347円264円240円 I.md" @@ -5,29 +5,57 @@ ## 题目大意 -给定两个没有重复元素的数组 `nums1` 和 `nums2` ,其中 `nums1` 是 `nums2` 的子集。 +**描述**:给定两个没有重复元素的数组 `nums1` 和 `nums2` ,其中 `nums1` 是 `nums2` 的子集。 -要求:找出 `nums1` 中每个元素在 `nums2` 中的下一个比其大的值。 +**要求**:找出 `nums1` 中每个元素在 `nums2` 中的下一个比其大的值。 + +**说明**: - `nums1` 中数字 `x` 的下一个更大元素是指: `x` 在 `nums2` 中对应位置的右边的第一个比 `x` 大的元素。如果不存在,对应位置输出 `-1`。 +- 1ドル \le nums1.length \le nums2.length \le 1000$。 +- 0ドル \le nums1[i], nums2[i] \le 10^4$。 +- $nums1$ 和 $nums2$ 中所有整数互不相同。 +- $nums1$ 中的所有整数同样出现在 $nums2$ 中。 + +**示例**: + +```Python +输入:nums1 = [4,1,2], nums2 = [1,3,4,2]. +输出:[-1,3,-1] +解释:nums1 中每个值的下一个更大元素如下所述: +- 4 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。 +- 1 ,用加粗斜体标识,nums2 = [1,3,4,2]。下一个更大元素是 3 。 +- 2 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。 + + +输入:nums1 = [2,4], nums2 = [1,2,3,4]. +输出:[3,-1] +解释:nums1 中每个值的下一个更大元素如下所述: +- 2 ,用加粗斜体标识,nums2 = [1,2,3,4]。下一个更大元素是 3 。 +- 4 ,用加粗斜体标识,nums2 = [1,2,3,4]。不存在下一个更大元素,所以答案是 -1 。 +``` ## 解题思路 -第一种思路是根据题意直接暴力求解。遍历 `nums1` 中的每一个元素。对于 `nums1` 的每一个元素 `nums1[i]`,再遍历一遍 `nums2`,查找 `nums2` 中对应位置右边第一个比 `nums1[i]` 大的元素。这种解法的时间复杂度是 $O(n^2)$。 +最直接的思路是根据题意直接暴力求解。遍历 `nums1` 中的每一个元素。对于 `nums1` 的每一个元素 `nums1[i]`,再遍历一遍 `nums2`,查找 `nums2` 中对应位置右边第一个比 `nums1[i]` 大的元素。这种解法的时间复杂度是 $O(n^2)$。 + +另一种思路是单调栈。 + +### 思路 1:单调栈 -第二种思路是使用单调递增栈。因为 `nums1` 是 `nums2` 的子集,所以我们可以先遍历一遍 `nums2`,并构造单调递增栈,求出 `nums2` 中每个元素右侧下一个更大的元素。然后将其存储到哈希表中。然后再遍历一遍 `nums1`,从哈希表中取出对应结果,存放到答案数组中。这种解法的时间复杂度是 $O(n)$。具体做法如下: +因为 `nums1` 是 `nums2` 的子集,所以我们可以先遍历一遍 `nums2`,并构造单调递增栈,求出 `nums2` 中每个元素右侧下一个更大的元素。然后将其存储到哈希表中。然后再遍历一遍 `nums1`,从哈希表中取出对应结果,存放到答案数组中。这种解法的时间复杂度是 $O(n)$。具体做法如下: -- 使用数组 `res` 存放答案。使用 `stack` 表示单调递增栈。使用哈希表 `num_map` 用于存储 `nums2` 中下一个比当前元素大的数值,映射关系为 `当前元素值:下一个比当前元素大的数值`。 -- 遍历数组 `nums2`,对于当前元素: - - 如果当前元素值较小,则直接让当前元素值入栈。 - - 如果当前元素值较大,则一直出栈,直到当前元素值小于栈顶元素。 - - 出栈时,第一个大于栈顶元素值的元素,就是当前元素。则将其映射到 `num_map` 中。 +1. 使用数组 `res` 存放答案。使用 `stack` 表示单调递增栈。使用哈希表 `num_map` 用于存储 `nums2` 中下一个比当前元素大的数值,映射关系为 `当前元素值:下一个比当前元素大的数值`。 -- 遍历完数组 `nums2`,建立好所有元素下一个更大元素的映射关系之后,再遍历数组 `nums1`。 -- 从 `num_map` 中取出对应的值,将其加入到答案数组中。 -- 最终输出答案数组 `res`。 +2. 遍历数组 `nums2`,对于当前元素: + 1. 如果当前元素值较小,则直接让当前元素值入栈。 + 2. 如果当前元素值较大,则一直出栈,直到当前元素值小于栈顶元素。 + 1. 出栈时,第一个大于栈顶元素值的元素,就是当前元素。则将其映射到 `num_map` 中。 +3. 遍历完数组 `nums2`,建立好所有元素下一个更大元素的映射关系之后,再遍历数组 `nums1`。 +4. 从 `num_map` 中取出对应的值,将其加入到答案数组中。 +5. 最终输出答案数组 `res`。 -## 代码 +### 思路 1:代码 ```Python class Solution: @@ -46,3 +74,8 @@ class Solution: return res ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n)$。 +- **空间复杂度**:$O(n)$。 + diff --git "a/Solutions/0739. 346円257円217円346円227円245円346円270円251円345円272円246円.md" "b/Solutions/0739. 346円257円217円346円227円245円346円270円251円345円272円246円.md" index ab9a206b..306aa35a 100644 --- "a/Solutions/0739. 346円257円217円346円227円245円346円270円251円345円272円246円.md" +++ "b/Solutions/0739. 346円257円217円346円227円245円346円270円251円345円272円246円.md" @@ -5,9 +5,25 @@ ## 题目大意 -给定一个列表 `temperatures`,每一个位置对应每天的气温。 +**描述**:给定一个列表 `temperatures`,`temperatures[i]` 表示第 `i` 天的气温。 -要求:输出一个列表,列表上每个位置代表如果要观测到更高的气温,至少需要等待的天数。如果之后的气温不再升高,则用 `0` 来代替。 +**要求**:输出一个列表,列表上每个位置代表「如果要观测到更高的气温,至少需要等待的天数」。如果之后的气温不再升高,则用 `0` 来代替。 + +**说明**: + +- 1ドル \le temperatures.length \le 10^5$。 +- 30ドル \le temperatures[i] \le 100$。 + +**示例**: + +```Python +输入: temperatures = [73,74,75,71,69,72,76,73] +输出: [1,1,4,2,1,1,0,0] + + +输入: temperatures = [30,40,50,60] +输出: [1,1,1,0] +``` ## 解题思路 @@ -15,16 +31,18 @@ 最简单的思路是对于每个温度值,向后依次进行搜索,找到比当前温度更高的值。 -更好的方式使用「单调递增栈」。栈中保存元素的下标。 +更好的方式使用「单调递增栈」,栈中保存元素的下标。 + +### 思路 1:单调栈 -- 首先,将答案数组 `ans` 全部赋值为 0。然后遍历数组每个位置元素。 -- 如果栈为空,则将当前元素的下标入栈。 -- 如果栈不为空,且当前数字大于栈顶元素对应数字,则栈顶元素出栈,并计算下标差。 - - 此时当前元素就是栈顶元素的下一个更高值,将其下标差存入答案数组 `ans` 中保存起来,判断栈顶元素。 -- 直到当前数字小于或等于栈顶元素,则停止出栈,将当前元素下标入栈。 -- 最后输出答案数组 `ans`。 +1. 首先,将答案数组 `ans` 全部赋值为 0。然后遍历数组每个位置元素。 +2. 如果栈为空,则将当前元素的下标入栈。 +3. 如果栈不为空,且当前数字大于栈顶元素对应数字,则栈顶元素出栈,并计算下标差。 +4. 此时当前元素就是栈顶元素的下一个更高值,将其下标差存入答案数组 `ans` 中保存起来,判断栈顶元素。 +5. 直到当前数字小于或等于栈顶元素,则停止出栈,将当前元素下标入栈。 +6. 最后输出答案数组 `ans`。 -## 代码 +### 思路 1:代码 ```Python class Solution: @@ -40,3 +58,8 @@ class Solution: return ans ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n)$。 +- **空间复杂度**:$O(n)$。 + diff --git "a/Solutions/0946. 351円252円214円350円257円201円346円240円210円345円272円217円345円210円227円.md" "b/Solutions/0946. 351円252円214円350円257円201円346円240円210円345円272円217円345円210円227円.md" index 5024c97a..0e38acfa 100644 --- "a/Solutions/0946. 351円252円214円350円257円201円346円240円210円345円272円217円345円210円227円.md" +++ "b/Solutions/0946. 351円252円214円350円257円201円346円240円210円345円272円217円345円210円227円.md" @@ -5,15 +5,40 @@ ## 题目大意 -给定两个整数序列 `pushed` 和 `popped`,每个序列中的值都不重复。 +**描述**:给定两个整数序列 `pushed` 和 `popped`,每个序列中的值都不重复。 -要求:如果第一个序列为空栈的压入顺序,而第二个序列 `popped` 为该栈的压出序列,则返回 `True`,否则返回 `False`。 +**要求**:如果第一个序列为空栈的压入顺序,而第二个序列 `popped` 为该栈的压出序列,则返回 `True`,否则返回 `False`。 + +**说明**: + +- 1ドル \le pushed.length \le 1000$。 +- 0ドル \le pushed[i] \le 1000$。 +- $pushed$ 的所有元素互不相同。 +- $popped.length == pushed.length$。 +- $popped$ 是 $pushed$ 的一个排列。 + +**示例**: + +```Python +输入:pushed = [1,2,3,4,5], popped = [4,5,3,2,1] +输出:true +解释:我们可以按以下顺序执行: +push(1), push(2), push(3), push(4), pop() -> 4, +push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1 + + +输入:pushed = [1,2,3,4,5], popped = [4,3,5,1,2] +输出:false +解释:1 不能在 2 之前弹出。 +``` ## 解题思路 +### 思路 1:栈 + 借助一个栈来模拟压入、压出的操作。检测最后是否能模拟成功。 -## 代码 +### 思路 1:代码 ```Python class Solution: @@ -29,3 +54,8 @@ class Solution: return len(stack) == 0 ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n)$。 +- **空间复杂度**:$O(n)$。 + diff --git "a/Solutions/1081. 344円270円215円345円220円214円345円255円227円347円254円246円347円232円204円346円234円200円345円260円217円345円255円220円345円272円217円345円210円227円.md" "b/Solutions/1081. 344円270円215円345円220円214円345円255円227円347円254円246円347円232円204円346円234円200円345円260円217円345円255円220円345円272円217円345円210円227円.md" index 663b89a6..adfb8c26 100644 --- "a/Solutions/1081. 344円270円215円345円220円214円345円255円227円347円254円246円347円232円204円346円234円200円345円260円217円345円255円220円345円272円217円345円210円227円.md" +++ "b/Solutions/1081. 344円270円215円345円220円214円345円255円227円347円254円246円347円232円204円346円234円200円345円260円217円345円255円220円345円272円217円345円210円227円.md" @@ -5,36 +5,54 @@ ## 题目大意 -给定一个字符串 `s`。 +**描述**:给定一个字符串 `s`。 -要求:返回 `s` 字典序最小的子序列,该子序列包含 `s` 的所有不同字符,且只包含一次。 +**要求**:去除字符串中重复的字母,使得每个字母只出现一次。需要保证 **「返回结果的字典序最小(要求不能打乱其他字符的相对位置)」**。 + +**说明**: + +- 1ドル \le s.length \le 10^4$。 +- `s` 由小写英文字母组成。 + +**示例**: + +```Python +输入:s = "bcabc" +输出:"abc" + + +输入:s = "cbacdcbc" +输出:"acdb" +``` ## 解题思路 -针对题目的两个要求:包含所有不同字符,且只包含一次(去重)、子序列(不能打乱其他字符顺序)、字典序最小。我们来一一进行分析。 +### 思路 1:哈希表 + 单调栈 -1. 包含所有不同字符,且只包含一次(去重):可以通过 **「使用哈希表存储字母出现次数」** 的方式,将每个字母出现的次数统计起来,再遍历一遍,去除重复的字母。 -2. 子序列(不能打乱其他字符顺序):按顺序遍历,将非重复的字母存储到答案数组或者栈中,最后再拼接起来,就能保证不打乱其他字符顺序。 -3. 字典序最小:意味着字典序小的字母应该尽可能放在前面。 - - 对于第 `i` 个字符 `s[i]` 而言,如果第 `0` ~ `i - 1` 之间的某个字符 `s[j]` 在 `s[i]` 之后不再出现了,那么 `s[j]` 必须放到 `s[i]` 之前。 - - 而如果 `s[j]` 在之后还会出现,并且 `s[j]` 的字典序大于 `s[i]`,我们则可以先舍弃 `s[j]`,把 `s[i]` 尽可能的放到前面。后边再考虑使用 `s[j]` 所对应的字符。 +针对题目的三个要求:去重、不能打乱其他字符顺序、字典序最小。我们来一一分析。 -要满足第 3 条需求,我们可以使用 **「单调栈」** 来解决。我们使用单调栈存储 `s[i]` 之前出现的非重复、并且字典序最小的字符序列。整个算法步骤如下: +1. **去重**:可以通过 **「使用哈希表存储字母出现次数」** 的方式,将每个字母出现的次数统计起来,再遍历一遍,去除重复的字母。 +2. **不能打乱其他字符顺序**:按顺序遍历,将非重复的字母存储到答案数组或者栈中,最后再拼接起来,就能保证不打乱其他字符顺序。 +3. **字典序最小**:意味着字典序小的字母应该尽可能放在前面。 + 1. 对于第 `i` 个字符 `s[i]` 而言,如果第 `0` ~ `i - 1` 之间的某个字符 `s[j]` 在 `s[i]` 之后不再出现了,那么 `s[j]` 必须放到 `s[i]` 之前。 + 2. 而如果 `s[j]` 在之后还会出现,并且 `s[j]` 的字典序大于 `s[i]`,我们则可以先舍弃 `s[j]`,把 `s[i]` 尽可能的放到前面。后边再考虑使用 `s[j]` 所对应的字符。 -- 先遍历一遍字符串,用哈希表 `letter_counts` 统计出每个字母出现的次数。 -- 然后使用单调递减栈保存当前字符之前出现的非重复、并且字典序最小的字符序列。 -- 当遍历到 `s[i]` 时,如果 `s[i]` 没有在栈中出现过: - - 则比较 `s[i]` 和栈顶元素 `stack[-1]` 的字典序。如果 `s[i]` 的字典序小于栈顶元素 `stack[-1]`,并且栈顶元素之后的出现次数大于 `0`,则将栈顶元素弹出。 - - 然后继续判断 `s[i]` 和栈顶元素 `stack[-1]`,并且知道栈顶元素出现次数为 `0` 时停止弹出。此时将 `s[i]` 添加到单调栈中。 -- 从哈希表 `letter_counts` 中减去 `s[i]` 出现的次数,继续遍历。 -- 最后将单调栈中的字符依次拼接为答案字符串,并返回。 +要满足第 3 条需求,我们可以使用 **「单调栈」** 来解决。我们使用单调栈存储 `s[i]` 之前出现的非重复、并且字典序最小的字符序列。整个算法步骤如下: + +1. 先遍历一遍字符串,用哈希表 `letter_counts` 统计出每个字母出现的次数。 +2. 然后使用单调递减栈保存当前字符之前出现的非重复、并且字典序最小的字符序列。 +3. 当遍历到 `s[i]` 时,如果 `s[i]` 没有在栈中出现过: + 1. 比较 `s[i]` 和栈顶元素 `stack[-1]` 的字典序。如果 `s[i]` 的字典序小于栈顶元素 `stack[-1]`,并且栈顶元素之后的出现次数大于 `0`,则将栈顶元素弹出。 + 2. 然后继续判断 `s[i]` 和栈顶元素 `stack[-1]`,并且知道栈顶元素出现次数为 `0` 时停止弹出。此时将 `s[i]` 添加到单调栈中。 +4. 从哈希表 `letter_counts` 中减去 `s[i]` 出现的次数,继续遍历。 +5. 最后将单调栈中的字符依次拼接为答案字符串,并返回。 -## 代码 +### 思路 1:代码 ```Python class Solution: - def smallestSubsequence(self, s: str) -> str: + def removeDuplicateLetters(self, s: str) -> str: stack = [] letter_counts = dict() for ch in s: @@ -53,3 +71,11 @@ class Solution: return ''.join(stack) ``` +### 思路 1:复杂度分析 + +- **时间复杂度**:$O(n)$。 +- **空间复杂度**:$O(|\sum|),ドル其中 $\sum$ 为字符集合,$|\sum|$ 为字符种类个数。由于栈中字符不能重复,因此栈中最多有 $|\sum|$ 个字符。 + +## 参考资料 + +- 【题解】[去除重复数组 - 去除重复字母 - 力扣(LeetCode)](https://leetcode.cn/problems/remove-duplicate-letters/solution/qu-chu-zhong-fu-shu-zu-by-lu-shi-zhe-sokp/) \ No newline at end of file