文章目录
- 一【题目类别】
- 二【题目难度】
- 三【题目编号】
- 四【题目描述】
- 五【题目示例】
- 六【题目提示】
- 七【解题思路】
- 八【时间频度】
- 九【代码实现】
- 十【提交结果】
一【题目类别】
- 广度优先搜索
二【题目难度】
- 困难
三【题目编号】
- 301.删除无效的括号
四【题目描述】
- 给你一个由若干括号和字母组成的字符串
s
,删除最小数量的无效括号,使得输入的字符串有效。 - 返回所有可能的结果。答案可以按 任意顺序 返回。
五【题目示例】
-
示例 1:
- 输入:
s = "()())()"
- 输出:
["(())()","()()()"]
- 输入:
-
示例 2:
- 输入:
s = "(a)())()"
- 输出:
["(a())()","(a)()()"]
- 输入:
-
示例 3:
- 输入:s =
")("
- 输出:
[""]
- 输入:s =
六【题目提示】
1 <= s.length <= 25
s
由小写英文字母以及括号'('
和')'
组成s
中至多含20
个括号
七【解题思路】
- 这道题我觉得还是挺难的,虽然没用到什么特别的算法,不过很难想到(我个人感觉)
- 要解决这道题我们首先要考虑使用什么方法,我们仔细阅读题目后发现一个细节,即删除最少数量的无效括号以达到目的
- 既然要最少数量,我们想是不是可以每次删除一个括号,然后下一次以每次删除后的结果继续向下删除括号以测试现在的括号是否有效呢?
- 这个思路显然是可以的,并且由于每次只删除一个括号,所以显然满足题目要求的最少次数,而且自然的想到了广度优先搜索:
- 队列中初始化为输入字符串
- 然后进入广度优先遍历算法
- 每次首先判断当前得到的字符串中是否存在满足要求的括号序列(写一个函数判断,这个很简单)
- 如果存在满足要求的括号序列,直接返回结果即可
- 如果不存在满足要求的括号序列,就在上次处理的结果上,继续逐个删除括号,在下一层继续判断是否存在满足要求的括号序列
- 最后返回结果即可
- 具体细节可以参考下面的代码
八【时间频度】
- 时间复杂度: O ( n × 2 n ) O(n \times 2^n) O(n×2n), n n n为字符串的长度
- 空间复杂度: O ( n × C n n 2 ) O(n \times C_{n}^{\frac{n}{2}}) O(n×Cn2n), n n n为字符串的长度
九【代码实现】
- Java语言版
class Solution {
public List<String> removeInvalidParentheses(String s) {
// 存储结果
List<String> res = new ArrayList<String>();
// 存储当前层字符串的集合(去重)
Set<String> curLevel = new HashSet<String>();
curLevel.add(s);
// 使用广度优先遍历算法删除无效的括号
while (true) {
// 查看当前层字符串的集合是否存在满足要求的字符串序列
for (String str : curLevel) {
if (isValid(str)) {
res.add(str);
}
}
// 若找到满足要求的字符串序列,直接返回
if (res.size() > 0) {
return res;
}
// 存储下一层字符串的集合(去重)
Set<String> nextLevel = new HashSet<String>();
// 根据上一层的结果计算下一层的字符序列
for (String str : curLevel) {
for (int i = 0; i < str.length(); i++) {
// 避免重复计算
if (i > 0 && str.charAt(i) == str.charAt(i - 1)) {
continue;
}
// 每个位置的括号都要删除一次
if (str.charAt(i) == '(' || str.charAt(i) == ')') {
nextLevel.add(str.substring(0, i) + str.substring(i + 1, str.length()));
}
}
}
// 开始以下一层为基准进行下一批次的遍历
curLevel = nextLevel;
}
}
// 判断给定的括号序列是否有效
private boolean isValid(String str) {
char[] strs = str.toCharArray();
int count = 0;
for (char s : strs) {
if (s == '(') {
count++;
} else if (s == ')') {
count--;
if (count < 0 ) {
return false;
}
}
}
return count == 0;
}
}
- Python语言版
class Solution:
def removeInvalidParentheses(self, s: str) -> List[str]:
# 判断给定的括号序列是否有效
def isValid(string):
count = 0
for s in string:
if s == "(":
count += 1
elif s == ")":
count -= 1
if count < 0:
return False
return count == 0
# 存储结果
res = []
# 存储当前层字符串的集合(去重)
cur_level = set([s])
# 使用广度优先遍历算法删除无效的括号
while True:
# 查看当前层字符串的集合是否存在满足要求的字符串序列
for string in cur_level:
if isValid(string):
res.append(string)
# 若找到满足要求的字符串序列,直接返回
if len(res) > 0:
return res
# 存储下一层字符串的集合(去重)
next_level = set()
# 根据上一层的结果计算下一层的字符序列
for string in cur_level:
for i in range(len(string)):
# 避免重复计算
if i > 0 and string[i] == s[i - 1]:
continue
# 每个位置的括号都要删除一次
if string[i] == "(" or string[i] == ")":
next_level.add(string[:i] + string[i + 1:])
# 开始以下一层为基准进行下一批次的遍历
cur_level = next_level
# 返回结果
return res
- C++语言版
class Solution {
public:
// 判断给定的括号序列是否有效
bool isValid(string str) {
int count = 0;
for (char s : str) {
if (s == '(') {
count++;
} else if (s == ')') {
count--;
if (count < 0) {
return false;
}
}
}
return count == 0;
}
vector<string> removeInvalidParentheses(string s) {
// 存储结果
vector<string> res;
// 存储当前层字符串的集合(去重)
unordered_set<string> curLevel;
curLevel.insert(s);
// 使用广度优先遍历算法删除无效的括号
while(true) {
// 查看当前层字符串的集合是否存在满足要求的字符串序列
for (auto & str : curLevel) {
if (isValid(str)) {
res.emplace_back(str);
}
}
// 找到满足要求的字符串序列,直接返回
if (res.size() > 0) {
return res;
}
// 存储下一层字符串的集合(去重)
unordered_set<string> nextLevel;
// 根据上一层的结果计算下一层的字符序列
for (auto & str : curLevel) {
for(int i = 0; i < str.size(); i++) {
// 避免重复计算
if(i > 0 && str[i] == str[i - 1]) {
continue;
}
// 每个位置的括号都要删除一次
if (str[i] == '(' || str[i] == ')') {
nextLevel.insert(str.substr(0, i) + str.substr(i + 1, str.size()));
}
}
}
// 开始以下一层为基准进行下一批次的遍历
curLevel = nextLevel;
}
// 返回结果
return res;
}
};
十【提交结果】
-
Java语言版
-
Python语言版
-
C++语言版