笔者在解决力扣678题时,分别采用了贪婪法和回溯法对其进行解决。

678. 有效的括号字符串

给定一个只包含三种字符的字符串:( ,) 和 *,写一个函数来检验这个字符串是否为有效字符串。有效字符串具有如下规则:

任何左括号 ( 必须有相应的右括号 )。

任何右括号 ) 必须有相应的左括号 ( 。

左括号 ( 必须在对应的右括号之前 )。

  • 可以被视为单个右括号 ) ,或单个左括号 ( ,或一个空字符串。

一个空字符串也被视为有效字符串。

示例 1:

输入: “()”

输出: True

示例 2:

输入: “(*)”

输出: True

示例 3:

输入: “(*))”

输出: True

注意:

字符串大小将在 [1,100] 范围内。

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/valid-parenthesis-string

贪婪法
在这里,需要根据题目来弄明白条件,式子成立的条件是:左括号不可能是小于0的,正常情况下,如果左括号小于0,那肯定是使用的*号作为左括号的次数太多了,而且右括号不能小于0,如果为0说明,右括号太多了,右括号右边的左括号不可能来挽救这个右括号了。

  1. class Solution {
  2. public:
  3. bool checkValidString(string s) {
  4. int lo = 0, hi = 0;
  5. for(auto &ch : s)
  6. {
  7. lo += ch == '(' ? 1 : -1;
  8. hi += ch != ')' ? 1 : -1;
  9. if(hi < 0)
  10. return false;
  11. lo = max(lo, 0);
  12. }
  13. if(lo == 0)
  14. return true;
  15. else
  16. return false;
  17. }
  18. };

完成一次字符串遍历,因此时间复杂度为O(N)
使用了lo, hi两个变量,因此空间复杂度为O(1)

下图是空间和时间的消耗情况
image.png

回溯法

  1. class Solution {
  2. public:
  3. map<pair<stack<char>, string>, bool>store;
  4. bool subcheck(stack<char>par, string s)
  5. {
  6. if(!par.empty() && s == "")
  7. return false;
  8. if(par.empty() && s == "")
  9. return true;
  10. pair<stack<char>, string>curpair{par, s};
  11. if(store.find(curpair) != store.end())
  12. return store[curpair];
  13. for(int i = 0; i < s.size(); i++)
  14. {
  15. if(s[i] == '(')
  16. {
  17. par.push('(');
  18. }
  19. else if(s[i] == ')')
  20. {
  21. if(par.empty())
  22. {
  23. store[curpair] = false;
  24. return false;
  25. }
  26. else
  27. {
  28. par.pop();
  29. }
  30. }
  31. else
  32. {
  33. string tmp = s.substr(i + 1, s.size() - i - 1);
  34. store[curpair] = (subcheck(par, '(' + tmp) || subcheck(par, tmp) || subcheck(par, ')' + tmp));
  35. return store[curpair];
  36. }
  37. }
  38. if(par.empty())
  39. {
  40. store[curpair] = true;
  41. return true;
  42. }
  43. else
  44. {
  45. store[curpair] = false;
  46. return false;
  47. }
  48. }
  49. bool checkValidString(string s) {
  50. int size = s.size();
  51. if(size == 0)
  52. return true;
  53. if(size == 1)
  54. {
  55. if(s == "*")
  56. return true;
  57. else
  58. return false;
  59. }
  60. stack<char>par;
  61. for(int i = 0; i < size; i++)
  62. {
  63. if(s[i] == '(')
  64. par.push('(');
  65. else if(s[i] == ')')
  66. {
  67. if(par.empty())
  68. return false;
  69. else
  70. par.pop();
  71. }
  72. else
  73. {
  74. string tmp = s.substr(i + 1, s.size() - i - 1);
  75. return (subcheck(par, '(' + tmp) || subcheck(par, tmp) || subcheck(par, ')' + tmp));
  76. }
  77. }
  78. if(par.empty())
  79. return true;
  80. else
  81. return false;
  82. }
  83. };

下图是空间的消耗情况

image.png