You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 lines
2.8 KiB

2 years ago
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;
}
}