From b94ff8de589520bbf8d776096aef56abe8463aad Mon Sep 17 00:00:00 2001 From: heimoshuiyu Date: Tue, 10 Jan 2023 01:23:49 +0800 Subject: [PATCH] leetcode-20230106.md --- index.html | 5 +- leetcode-20230106.md | 154 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+), 2 deletions(-) create mode 100644 leetcode-20230106.md diff --git a/index.html b/index.html index c3ec7910..fd742671 100644 --- a/index.html +++ b/index.html @@ -16,8 +16,7 @@
-
Slide 1
-
Slide 2
+
@@ -31,6 +30,8 @@ // - https://revealjs.com/config/ Reveal.initialize({ hash: true, + height: 1000, + width: 1000, // Learn about plugins: https://revealjs.com/plugins/ plugins: [ RevealMarkdown, RevealHighlight, RevealNotes ] diff --git a/leetcode-20230106.md b/leetcode-20230106.md new file mode 100644 index 00000000..1dbca737 --- /dev/null +++ b/leetcode-20230106.md @@ -0,0 +1,154 @@ +### Leetcode 💻 寒假 20230106 + +--- + +### 20. Valid Parentheses + +验证左右括号是否匹配 (利用Stack) + +```cpp [|3-11|12-20|22-24|26|28|29-32|34-40|44|] +class Solution { +public: + // 判断左右括号是否相等 + inline bool match(const char &left, const char &right) { + switch (left) { + case '(': return right == ')'; + case '{': return right == '}'; + case '[': return right == ']'; + } + return false; + } + // 判断是不是左括号 + inline bool is_left(const char &c) { + switch (c) { + case '(': return true; + case '{': return true; + case '[': return true; + } + return false; + } + bool isValid(string s) { + // 判断长度是否为偶数 + if (s.length() % 2 != 0) + return false; + + stack myStack; + + for (auto const &c : s) { + if (is_left(c)) { + myStack.push(c); + continue; + } + + if (myStack.empty()) + return false; + + if (!match(myStack.top(), c)) + return false; + + myStack.pop(); + } + + // 如果结束之后 stack 中还有元素 + return myStack.empty(); + } +}; +``` + +Note: + +3-10 首先有两个辅助函数,一个叫match,用来判断左右括号是否相等, + +12-20 然后是另一个函数慵懒判断是不是左括号。 + +22-24 进入主函数,先判断一下字符串长度是基数还是偶数, +如果是基数说明里面的括号肯定是不能左右匹配的,就可以直接返回false + +26 然后创建一个stack类型的变量myStack + +28 然后用变量c去遍历s,这里用到的是c++11的语法,auto是自动推断类型, +const表示c是不能被更改的,and符号表示这是一个左值引用, +c的类型可以简单理解为字符串中的字符 + +29-32 如果c是左括号,那么直接往stack中添加这个c,然后直接进入下一个循环 + +34-40 刚刚的语句已经把做括号的情况处理掉了,那么剩下的情况就是c是右括号的情况。 +我们先检查stack中是否为空,为空的话说明stack中没有括号可以和c互相对应, +那么让函数返回false。 +接著取stack中最顶的括号和c进行配对,如果不匹配返回false。 +最后调用stack的pop方法,移除stack中最顶部的括号。 + +44 最后的最后,所有字符都匹配完了,如果stack中还残留有括号, +说明这个字符串也是不匹配的 + +--- + +### 84. Largest Rectangle in Histogram + +```cpp [|2-4|6-8|26-28|9-10|12-14|16-20|23|26-31|] +int largestRectangleArea(vector &heights) { + int ans = 0; + // 定义 stack 储存增序长方形 + stack order; + + // 往 stack 中添加位于 index 的高度 height 的长方形 + auto append = [&ans, &order, &heights] + (int index, int value) -> void { + // 计算单个长方形面积 + ans = max(ans, value); + + // stack 不为空 且 需要添加的长方形矮于 stack 中的长方形 + while (!order.empty() && + value < heights[order.top()]) { + + // 计算面积 + int h = heights[order.top()]; + order.pop(); + int w = index - 1 - (order.empty() ? -1 : order.top()); + ans = max(ans, h * w); + } + + order.push(index); + }; + + for (int i = 0; i < heights.size(); i++) { + append(i, heights[i]); + } + // 处理edge case, 在最末尾添加一个高度为-1的长方形, + // 这将会计算stack中所有残留的长方形的面积 + append(heights.size(), -1); + + return ans; +} +``` + +Note: + +2-4 首先定义一个整数变量answer,代表这道题的计算结果, +然后定义一个stack,元素类型是整数,用来储存长方形的索引, +注意是储存的是长方形的索引不是长方形的高度。 + +6-8 然后由于这部分代码要在多个地方被调用,所以这里我用了c++11的匿名函数, +append是函数名,它接受两个参数,一个是index一个是value,它没有返回值,所以是void。 +同时这个函数可以访问并修改ans,order,height,这里的and符号是表示捕获引用变量的意思, +各位理解为这个函数可以在函数内修改到函数外的变量就行了。 + +26-28 定义好函数之后会在一个循环中遍历题目给的这个高度列表, +然后调用函数,传入每个长方形的索引和高度 + +9-10 进入函数后首先计算单个长方形的面积 + +12-14 然后进入一个循环, +循环的条件是stack 不为空 且 需要添加的长方形矮于 stack 中的长方形 + +16-20 在循环内获得高度h和宽度w,注意这里先调用了pop然后在调用top, +如果stack里面是空的,那么调用top会引起奇怪的错误,所以一定要检查是否为空。 +这里用了一个三元表达式,如果空则返回-1,否则正常返回top. + +23 循环结束之后,也就是需要添加的长方形比stack中的长方形都高的时候, +我们可以把它添加仅stack了 + +26-31 这是刚刚看到调用append的代码 +注意代码运行到这里stack中是还有长方形的,stack中残留的长方形还没有计算面积。 +所以在最末尾的位置添加一个高度为-1的长方形, +由于stack中的所有长方形都是正数,加个-1进去会计算stack中残留的长方形面积。