|
|
package class_2022_07_3_week;
|
|
|
|
|
|
// 来自蔚来汽车
|
|
|
// 给定一个只包含三种字符的字符串:( 、) 和 *,
|
|
|
// 写一个函数来检验这个字符串是否为有效字符串。有效字符串具有如下规则:
|
|
|
// 任何左括号 ( 必须有相应的右括号 )。
|
|
|
// 任何右括号 ) 必须有相应的左括号 ( 。
|
|
|
// 左括号 ( 必须在对应的右括号之前 )。
|
|
|
// * 可以被视为单个右括号 ) ,或单个左括号 ( ,或一个空字符。
|
|
|
// 一个空字符串也被视为有效字符串。
|
|
|
// 测试链接 : https://leetcode.cn/problems/valid-parenthesis-string/
|
|
|
public class Code02_ValidParenthesisString {
|
|
|
|
|
|
public static boolean valid(String str) {
|
|
|
char[] s = str.toCharArray();
|
|
|
int n = s.length;
|
|
|
int[][] dp = new int[n][n + 1];
|
|
|
// dp[i][j] == 0 没算过!
|
|
|
// dp[i][j] == -1 算过了!结果是false!
|
|
|
// dp[i][j] == 1 算过了!结果是true!
|
|
|
return zuo(s, 0, 0, dp);
|
|
|
}
|
|
|
|
|
|
public static boolean zuo(char[] s, int i, int c, int[][] dp) {
|
|
|
if (i == s.length) {
|
|
|
return c == 0;
|
|
|
}
|
|
|
if (c < 0) {
|
|
|
return false;
|
|
|
}
|
|
|
if (dp[i][c] != 0) {
|
|
|
return dp[i][c] == 1;
|
|
|
}
|
|
|
boolean ans = false;
|
|
|
if (s[i] == '(') {
|
|
|
ans = zuo(s, i + 1, c + 1, dp);
|
|
|
} else if (s[i] == ')') {
|
|
|
ans = zuo(s, i + 1, c - 1, dp);
|
|
|
} else { // *
|
|
|
boolean p1 = zuo(s, i + 1, c + 1, dp);
|
|
|
boolean p2 = zuo(s, i + 1, c - 1, dp);
|
|
|
boolean p3 = zuo(s, i + 1, c, dp);
|
|
|
ans = p1 || p2 || p3;
|
|
|
}
|
|
|
dp[i][c] = ans ? 1 : -1;
|
|
|
return ans;
|
|
|
}
|
|
|
|
|
|
// 时间复杂度O(N平方)
|
|
|
// 从左往右的尝试
|
|
|
// 暴力递归改动态规划
|
|
|
public static boolean checkValidString1(String s) {
|
|
|
char[] str = s.toCharArray();
|
|
|
int n = str.length;
|
|
|
int[][] dp = new int[n][n];
|
|
|
return f(str, 0, 0, dp);
|
|
|
}
|
|
|
|
|
|
public static boolean f(char[] s, int i, int c, int[][] dp) {
|
|
|
if (i == s.length) {
|
|
|
return c == 0;
|
|
|
}
|
|
|
if (c < 0) {
|
|
|
return false;
|
|
|
}
|
|
|
if (c > s.length - i) {
|
|
|
return false;
|
|
|
}
|
|
|
if (dp[i][c] != 0) {
|
|
|
return dp[i][c] == 1;
|
|
|
}
|
|
|
boolean ans = false;
|
|
|
if (s[i] == '(') {
|
|
|
ans = f(s, i + 1, c + 1, dp);
|
|
|
} else if (s[i] == ')') {
|
|
|
ans = f(s, i + 1, c - 1, dp);
|
|
|
} else {
|
|
|
ans |= f(s, i + 1, c + 1, dp);
|
|
|
ans |= f(s, i + 1, c - 1, dp);
|
|
|
ans |= f(s, i + 1, c, dp);
|
|
|
}
|
|
|
dp[i][c] = ans ? 1 : -1;
|
|
|
return ans;
|
|
|
}
|
|
|
|
|
|
// 贪心方法
|
|
|
// 最优解
|
|
|
// 时间复杂度O(N),额外空间复杂度O(1)
|
|
|
public static boolean checkValidString2(String s) {
|
|
|
char[] str = s.toCharArray();
|
|
|
int max = 0;
|
|
|
int min = 0;
|
|
|
for (char x : str) {
|
|
|
if (x == '(') {
|
|
|
max++;
|
|
|
min++;
|
|
|
} else {
|
|
|
// ) *
|
|
|
if (x == ')' && max == 0) { // 不够减了!
|
|
|
return false;
|
|
|
}
|
|
|
// max 够减
|
|
|
// ) *
|
|
|
// max -1 +1
|
|
|
max += x == ')' ? -1 : 1;
|
|
|
// min ( - ) 弹性范围中,最小的差值
|
|
|
// ) * min -1
|
|
|
// min == 0
|
|
|
if (min > 0) {
|
|
|
min--;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
// 0 ~ 7
|
|
|
// 3 ~ 9
|
|
|
return min == 0;
|
|
|
}
|
|
|
|
|
|
}
|