题目描述
题目给出括号序列brackets,要求判断此序列是否合法。并且具体操作是将??改为'('或者')'。brackets只由'?','(',')'构成。
合法的括号序列的定义:
1.空字符为合法括号序列
2.(+合法括号序列+) 为合法括号序列
3.()+合法括号序列为合法括号序列
如果能构造出来则返回恢复后任意合法的括号序列,否则返回Impossible
方法一:暴力求解
求解思路
对于本题目的求解,我们可以用暴力遍历的方法,首先我们声明两个变量,index变量记录问号出现的下标,dp变量记录两个问号之间括号的差值,正数表示差相应右括号,负数表示差相应绝对值的左括号。然后我们字符串进行遍历,并且将index和dp进行赋值,然后第二次遍历字符串,对每个问号所在的位置进行判断,如果存在左括号数加上差值都小于右括号则返回impossible,同理右括号也一样进行判断。最后对问号进行替换如果左括号多,则记录数大于0,从右向左进行右括号替换,同理右括号多的情况也按上述操作。最终我们即可通过暴力解法得到本题的答案。
解题代码
class Solution { public: string MissingBrackets(string brackets) { int n = brackets.length(); if(n % 2) // 不为偶数一定不合法 return "Impossible"; vector<int> index; // index记录问号出现的位置 vector<int> mydp; // 记录两个问号之间左右括号个数的差 int a = 0; //维护两个问号之间左右括号个数的差 for(int i = 0; i < n; i++) { //找到?的位置,即之间的括号差 if(brackets[i] == '?') { index.push_back(i); // 位置入数组 mydp.push_back(a); a = 0; } else if(brackets[i] == ')') // 遇到左加,遇到右减 a--; else a++; } index.push_back(n); mydp.push_back(a); n = index.size(); a = 0; int q = 0; // 记录问号出现次数 for(int i = 0; i < n; i++) { a += mydp[i]; // 相差求和 if(-a > q++) // 如果前面一直少,且少得还大于?出现的次数 return "Impossible"; } if(-a > index.size() - 1) // 把所有问号变为左括号都不能使左括号数量大于右括号 return "Impossible"; if(a > 0) { //左括号较多 a++; for(int i = n - 2; i >= 0; i--) { if(a > 0) { brackets[index[i]] = ')'; a--; } else { brackets[index[i]] = '('; a++; } } } else { //右括号较多 a--; for(int i = 0; i < n - 1; i++) { if(a < 0) { a++; brackets[index[i]] = '('; } else { brackets[index[i]] = ')'; a--; } } } return brackets; // 返回结果 } };
复杂度分析
时间复杂度:一层循环,因此时间复杂度为
空间复杂度:使用辅助数组index[N],dp[N],因此空间复杂度为
方法二:贪心思想求解
求解思路
对于本题我们也可以使用贪心的思想进行求解,对于合法的括号序列,左括号和右括号是相匹配的,因此我们可以从括号数入手,每次贪心地将差的左括号或者右括号补齐,最后验证整个序列是否合法。
解题代码
class Solution { public: string MissingBrackets(string brackets) { int n = brackets.length(); int mycount = 0; // 存储括号数量 for(int i = 0; i < n; i++) // 统计左括号数 if(brackets[i] == '(') mycount++; if(n % 2 || mycount * 2 > n) // 不为偶数一定不合法,左括号数大于一般肯定不合法 return "Impossible"; int rest = n / 2 - mycount; // 还需要补充多少左括号 for(int i = 0; i < n; i++) { if(brackets[i] == '?' && rest != 0) { brackets[i] = '('; // 贪心思想对括号数进行更新 rest--; } else if(brackets[i] == '?') brackets[i] = ')'; } int all = 0; for(int i = 0; i < n; i++) { //检查修改后内容是否合法 if(brackets[i] == '(') all++; else if(brackets[i] == ')') all--; if(all < 0) return "Impossible"; } return brackets; // 返回结果 } };
复杂度分析
时间复杂度:一层循环,因此时间复杂度为
空间复杂度:没有使用额外的内存地址空间,因此空间复杂度为