translate interview/合法括号判定.md

This commit is contained in:
andavid
2020-03-04 11:32:52 +08:00
parent 642f4618ac
commit 9ab66823ed
2 changed files with 87 additions and 86 deletions

View File

@ -0,0 +1,87 @@
# Valid Parentheses
**Translator: [andavid](https://github.com/andavid)**
**Author: [labuladong](https://github.com/labuladong)**
The valid of parentheses is a very common and practical problem. For example, the editor and the compiler would check the code we wrote whether the parentheses were correctly closed. As our code might contain the characters '(', ')', '{', '}', '[' and ']', it's a little bit difficult to determine.
This article is on an algorithm problem about valid parentheses. I believe it will help you to come to a better understanding of stack.
The problem is very simple. Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.
```text
Input: "()[]{}"
Output: true
Input: "([)]"
Output: false
Input: "{[]}"
Output: true
```
Before solving this problem, let's lower the difficulty. If the given string contains only parentheses, i.e. '(' and ')', how to check if the string is valid?
## deal with parentheses
As the string contains only parentheses, if the string is valid we must make sure:
**every `)`'s left must have a corresponding `(`**.
For example: `()))((`, the two right parenthesis in the middle have no corresponding left parenthesis, so this string is not valid.
We can write out the algorithm according to this thought.
```cpp
bool isValid(string str) {
// the number of left parenthesis to be matched
int left = 0;
for (char c : str) {
if (c == '(')
left++;
else // encounter right parenthesis
left--;
if (left < 0)
return false;
}
return left == 0;
}
```
If the string contains only one parentheses, the algorithm above will work. As for the case with three kind of parentheses, At first I imitate this thought, define three variables `left1`, `left2` and `left3`, each handle one parentheses. Although we need to write a lot of if-else branches, it seems to solve the problem.
But actually, it doesn't work. For example, `(())` is valid in the case with one parentheses, while `[(])` is not valid in the case with multiple parentheses.
Only recording the number of times that left parenthesis occurs is not enough to make the right judgments. We need to increase the information we stored. We can use stack to imitate similar thoughts.
## deal with multiple parentheses
Stack is a FILO(first in last out) data structure. It's very useful in dealing with parentheses.
In this problem, we use a `left` stack instead of the `left` variable before. **Having left parenthesis into stack, as for right parenthesis, find the recent left parenthesis in the stack, and then check if matched.**.
```cpp
bool isValid(string str) {
stack<char> left;
for (char c : str) {
if (c == '(' || c == '{' || c == '[')
left.push(c);
else // character c is right parenthesis
if (!left.empty() && leftOf(c) == left.top())
left.pop();
else
// not match with recent left parenthesis
return false;
}
// whether all left parenthesis are matched
return left.empty();
}
char leftOf(char c) {
if (c == '}') return '{';
if (c == ')') return '(';
return '[';
}
```

View File

@ -1,86 +0,0 @@
# 如何判定括号合法性
对括号的合法性判断是一个很常见且实用的问题,比如说我们写的代码,编辑器和编译器都会检查括号是否正确闭合。而且我们的代码可能会包含三种括号 `[](){}`,判断起来有一点难度。
本文就来聊一道关于括号合法性判断的算法题,相信能加深你对**栈**这种数据结构的理解。
题目很简单,输入一个字符串,其中包含 `[](){}` 六种括号,请你判断这个字符串组成的括号是否合法。
```
Input: "()[]{}"
Output: true
Input: "([)]"
Output: false
Input: "{[]}"
Output: true
```
解决这个问题之前,我们先降低难度,思考一下,**如果只有一种括号 `()`**,应该如何判断字符串组成的括号是否合法呢?
### 一、处理一种括号
字符串中只有圆括号,如果想让括号字符串合法,那么必须做到:
**每个右括号 `)` 的左边必须有一个左括号 `(` 和它匹配**
比如说字符串 `()))((` 中,中间的两个右括号**左边**就没有左括号匹配,所以这个括号组合是不合法的。
那么根据这个思路,我们可以写出算法:
```cpp
bool isValid(string str) {
// 待匹配的左括号数量
int left = 0;
for (char c : str) {
if (c == '(')
left++;
else // 遇到右括号
left--;
if (left < 0)
return false;
}
return left == 0;
}
```
如果只有圆括号,这样就能正确判断合法性。对于三种括号的情况,我一开始想模仿这个思路,定义三个变量 `left1``left2``left3` 分别处理每种括号,虽然要多写不少 if else 分支,但是似乎可以解决问题。
但实际上直接照搬这种思路是不行的,比如说只有一个括号的情况下 `(())` 是合法的,但是多种括号的情况下, `[(])` 显然是不合法的。
仅仅记录每种左括号出现的次数已经不能做出正确判断了,我们要加大存储的信息量,可以利用栈来模仿类似的思路。
### 二、处理多种括号
栈是一种先进后出的数据结构,处理括号问题的时候尤其有用。
我们这道题就用一个名为 `left` 的栈代替之前思路中的 `left` 变量,**遇到左括号就入栈,遇到右括号就去栈中寻找最近的左括号,看是否匹配**。
```cpp
bool isValid(string str) {
stack<char> left;
for (char c : str) {
if (c == '(' || c == '{' || c == '[')
left.push(c);
else // 字符 c 是右括号
if (!left.empty() && leftOf(c) == left.top())
left.pop();
else
// 和最近的左括号不匹配
return false;
}
// 是否所有的左括号都被匹配了
return left.empty();
}
char leftOf(char c) {
if (c == '}') return '{';
if (c == ')') return '(';
return '[';
}
```
坚持原创高质量文章,致力于把算法问题讲清楚,欢迎关注我的公众号 labuladong 获取最新文章:
![labuladong](../pictures/labuladong.jpg)