From 58999df498e7468aa8539d91232cf660739b55b4 Mon Sep 17 00:00:00 2001 From: gameloader Date: Wed, 9 Oct 2024 20:44:45 +0800 Subject: [PATCH] leetcode update --- content/posts/leetcode.md | 147 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) diff --git a/content/posts/leetcode.md b/content/posts/leetcode.md index e24d8c0..60c20ac 100644 --- a/content/posts/leetcode.md +++ b/content/posts/leetcode.md @@ -14997,3 +14997,150 @@ public: } }; ``` + +## day223 2024-10-07 + +### 2696. Minimum String Length After Removing substrings + +You are given a string s consisting only of uppercase English letters. + +You can apply some operations to this string where, in one operation, you can remove any occurrence of one of the substrings "AB" or "CD" from s. + +Return the minimum possible length of the resulting string that you can obtain. + +Note that the string concatenates after removing the substring and could produce new "AB" or "CD" substrings. + +![1007RamtD7kRdtwY](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/1007RamtD7kRdtwY.png) + +### 题解 + +本题和之前做过的一些删除子字符串的题目有些相似,做这个题的时候突然想到这种删除的过程有点像玩过的经典同色消除游戏“祖玛”。黄色的球前后都是绿色的球,消掉黄色的球后绿色的球聚在一起可以再次被消掉,这个过程需要保存“前面存在某种颜色的球”这一状态,同时只有某种颜色的球被消掉后才会暴露出更前面的某种颜色的球。这样一想栈结构已经浮出脑海了,本题使用栈保存这两个子字符串的前置状态(这里是字符串AB中的A和CD中的C)。如果继续遍历时的字符能与栈顶字母匹配则将栈顶字母出栈。一旦不匹配就清空栈,重新入栈。 + +### 代码 + +```cpp +class Solution { +public: + int minLength(string s) { + stack pairs; + int delelen = 0; + for (char c : s){ + if (c == 'A' || c == 'C'){ + pairs.push(c); + continue; + }else if (c == 'D'){ + if (!pairs.empty() && pairs.top() == 'C'){ + pairs.pop(); + delelen += 2; + continue; + } + }else if(c == 'B'){ + if (!pairs.empty() && pairs.top() == 'A'){ + pairs.pop(); + delelen += 2; + continue; + } + } + if (!pairs.empty()){ + stack emptyStack; + swap(emptyStack,pairs); + } + } + return s.size()-delelen; + } +}; +``` + +## day224 2024-10-08 + +### 1963. Minimum Number of Swaps to Make the String Balanced + +You are given a 0-indexed string s of even length n. The string consists of exactly n / 2 opening brackets '[' and n / 2 closing brackets ']'. + +A string is called balanced if and only if: + +It is the empty string, or +It can be written as AB, where both A and B are balanced strings, or +It can be written as [C], where C is a balanced string. +You may swap the brackets at any two indices any number of times. + +Return the minimum number of swaps to make s balanced. + +![1008vifTrvQbe7RI](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/1008vifTrvQbe7RI.png) + +### 题解 + +本题也是一道括号匹配问题,题面为通过调换顺序让字符串中所有中括号都是匹配的。本题明确说明左括号和右括号的数量相同,即最终一定可以全部匹配。括号匹配问题离不开栈结构,对于左括号直接入栈,遇到右括号且同时栈顶为左括号则匹配成功,将栈顶左括号出栈。若栈中没有可供匹配的左括号,遇到右括号则将右括号当作左括号入栈同时将“调换”变量+1。继续正常匹配括号,直到字符串剩余未匹配长度和当前被“调换”的字符个数相同为止,被调换的字符个数即为最小交换次数。 + +这种情况下,可以发现栈中永远只存在左括号,因此只需记录当前栈中左括号的个数就足够了,无需真的将左括号放入栈中。 + +贪心完全是看题目后的直觉,隐约感觉这样解可能就是对的,再用题目示例验证一下发现确实能得到正确结果,但是不能光靠感觉解题,还是需要证明贪心的正确性。为什么贪心算法就能得到最优解呢。原因在于每次我们将出现不平衡位置的右括号与后面的左括号交换时,可以使交换的两个括号都能与某个对应括号匹配上,若后面的左括号本来是不匹配的,交换位置后一定可以匹配,因为至少还可以与被交换的右括号匹配,而对右括号同理。若本来是匹配的,则交换后其仍然是匹配的,也就是说至少不会更差,考虑右括号一定从不匹配变成匹配,则这种交换已经是局部最优选择,本题因为左右括号数量相同,最终一定可以全部匹配,则不断的局部最优最终可以得到全局最优。 + +### 代码 + +```cpp +class Solution { +public: + int minSwaps(string s) { + int result = 0; + int length = s.size(); + int stacklen = 0; + for (int i=0;i 0){ + stacklen--; + }else{ + stacklen++; + result++; + } + } + } + return result; + } +}; +``` +## day225 2024-10-09 +### 921. Minimum Add to Make Parentheses Valid +A parentheses string is valid if and only if: + +It is the empty string, +It can be written as AB (A concatenated with B), where A and B are valid strings, or +It can be written as (A), where A is a valid string. +You are given a parentheses string s. In one move, you can insert a parenthesis at any position of the string. + +For example, if s = "()))", you can insert an opening parenthesis to be "(()))" or a closing parenthesis to be "())))". +Return the minimum number of moves required to make s valid. + +![10090ZydPlF1SeVw](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/10090ZydPlF1SeVw.png) + +### 题解 +本题解法和昨天的题目类似,左括号可以放在栈中等待匹配,如果栈中为空且扫描到了右括号则必须要前面补充一个左括号与之匹配,此时要将添加括号的数量加1,最终将字符串全部扫描完成后,栈中剩余的左括号的数量即为无法匹配的左括号数量,需要添加相同数量的右括号来匹配,因此将添加括号数量加上该数量得到最终结果。同样,因为栈中保存的一直为左括号,因此无需真的构造一个栈并将左括号入栈,只需用一个变量标记当前栈中的数量即可。 + +### 代码 +```cpp +class Solution { +public: + int minAddToMakeValid(string s) { + int num = 0; + int result = 0; + for (char c : s){ + if (c == '('){ + num++; + }else if(c == ')'){ + if (num > 0){ + num--; + }else{ + result++; + } + } + } + result += num; + return result; + } +}; +```