给定一个字符串s,字符串s只包含以下三种字符: (,*,),请你判断 s是不是一个合法的括号字符串。合法括号字符串有如下规则:
1.左括号'('必须有对应的右括号')'
2.右括号')'必须有对应的左括号'('
3.左括号必须在对应的右括号前面
4.*可以视为单个左括号,也可以视为单个右括号,或者视为一个空字符
5.空字符串也视为合法的括号字符串
数据范围:
"()()"
true
"((*)"
true
"(*)"
true
"(((*)"
false
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param s string字符串
* @return bool布尔型
*/
public boolean isValidString (String s) {
// write code here
int left = 0, right = 0, star = 0;
for(int i = 0; i < s.length(); i++){
char c = s.charAt(i);
if(c == '('){
left ++;
}else if(c == ')'){
right ++;
}else{
star ++;
}
if(left + star < right) return false;
}
left = 0;
right = 0;
star = 0;
for(int i = s.length() - 1; i >= 0; i--){
char c = s.charAt(i);
if(c == '('){
left ++;
}else if(c == ')'){
right ++;
}else{
star ++;
}
if(right + star < left) return false;
}
return true;
}
} public boolean isValidString (String s) {
int low = 0;
int high = 0;
for (char c : s.toCharArray()) {
if (c == '(') {
// 对于 '(',两个计数器都增加
low++;
high++;
} else if (c == ')') {
// 对于 ')',两个计数器都减少
low--;
high--;
} else if (c == '*') {
// 对于 '*',low 可以减少,high 可以增加
low--;
high++;
}
// low 不应该小于 0
if (low < 0) {
low = 0;
}
// 如果 high 变为负数,意味着太多的右括号无法匹配
if (high < 0) {
return false;
}
}
// 如果 low 为 0,则说明存在一种可能的 '*' 分配方式使得所有括号都匹配
return low == 0;
} public boolean isValidString (String s) {
int m=0,n=0;
for(int i=0;i<s.length();i++){
if(s.charAt(i)==')')m--;
else m++;
if(s.charAt(s.length()-1-i)=='(')n--;
else n++;
if(m<0||n<0)return false;
}
return true;
} import java.util.*;
/**
* NC175 合法的括号字符串
* @author d3y1
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param s string字符串
* @return bool布尔型
*/
public boolean isValidString (String s) {
return solution1(s);
// return solution2(s);
// return solution3(s);
}
/**
* 栈
* @param s
* @return
*/
private boolean solution1(String s){
Stack<Integer> leftStack = new Stack<>();
Stack<Integer> starStack = new Stack<>();
char ch;
for(int i=0; i<s.length(); i++){
ch = s.charAt(i);
if(ch == '('){
leftStack.push(i);
}
else if(ch == '*'){
starStack.push(i);
}
else if(ch == ')'){
if(!leftStack.isEmpty()){
leftStack.pop();
}else if(!starStack.isEmpty()){
starStack.pop();
}else{
return false;
}
}
}
while(!leftStack.isEmpty()){
if(!starStack.isEmpty() && leftStack.peek()<starStack.peek()){
leftStack.pop();
starStack.pop();
}else{
return false;
}
}
return true;
}
/**
* 贪心
* @param s
* @return
*/
private boolean solution2(String s){
// 待消除左括号的最小个数
int minLeft = 0;
// 待消除左括号的最大个数
int maxLeft = 0;
for(char ch: s.toCharArray()){
if(ch == '('){
minLeft++;
maxLeft++;
}
else if(ch == '*'){
// * -> )
if(minLeft > 0){
minLeft--;
}
// * -> (
maxLeft++;
}
else if(ch == ')'){
if(minLeft > 0){
minLeft--;
}
// 已经没有'('或'*'与当前')'匹配
if(maxLeft == 0){
return false;
}
maxLeft--;
}
}
return minLeft==0;
}
/**
* 动态规划
*
* dp[i][j]表示子串s[i,j]是否为合法的括号字符串
*
* len=1:
* dp[i][i] = true , s.charAt(i) == '*'
*
* len=2:
* dp[i][i+1] = true , (currCh=='('||currCh=='*') && (nextCh==')'||nextCh=='*')
*
* len>=3:
* dp[i][j] = dp[i+1][j-1] , (leftCh=='('||leftCh=='*') && (rightCh==')'||rightCh=='*')
* dp[i][j] = dp[i][k]&&dp[k+1][j] , i<=k<j&&!dp[i][j]
*
* @param s
* @return
*/
private boolean solution3(String s){
int n = s.length();
boolean[][] dp = new boolean[n][n];
// len=1 -> *
for(int i=0; i<n; i++){
if(s.charAt(i) == '*'){
dp[i][i] = true;
}
}
// len=2 -> () (* *) **
char currCh,nextCh;
for(int i=0; i+1<n; i++){
currCh = s.charAt(i);
nextCh = s.charAt(i+1);
if((currCh=='('||currCh=='*') && (nextCh==')'||nextCh=='*')){
dp[i][i+1] = true;
}
}
// len>=3
char leftCh,rightCh;
for(int i=n-3; i>=0; i--){
for(int j=i+2; j<n; j++){
leftCh = s.charAt(i);
rightCh = s.charAt(j);
// (())
if((leftCh=='('||leftCh=='*') && (rightCh==')'||rightCh=='*')){
dp[i][j] = dp[i+1][j-1];
}
// ()()
// for(int k=i; k<j&&!dp[i][j]; k++){
// dp[i][j] = dp[i][k]&&dp[k+1][j];
// }
for(int k=i; k<j; k++){
if(dp[i][j]){
break;
}
dp[i][j] = dp[i][k]&&dp[k+1][j];
}
}
}
return dp[0][n-1];
}
} #
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param s string字符串
# @return bool布尔型
#
class Solution:
def isValidString(self , s: str) -> bool:
# write code here
star_stack = []
symbol_stack = []
for i in range(len(s)):
if s[i:i+1] == '(':
symbol_stack.append([i,'('])
elif s[i:i+1] == '*':
star_stack.append([i,'*'])
else:
if symbol_stack:
symbol_stack.pop()
continue
elif len(symbol_stack) == 0 and star_stack:
star_stack.pop()
continue
else:
return False
while symbol_stack:
if len(star_stack) == 0:
return False
if symbol_stack.pop()[0] > star_stack.pop()[0]:
return False
return True function isValidString(s) {
var stack = [];
var sArr = s.split('');
// 处理右括号
for(var i = 0; i < sArr.length; i++) {
var item = sArr[i];
if(item === '(' || item === '*') {
stack.push(item);
}
// 遇到右括号时,从栈里面去找最近的左括号,若找不到,则找最近的*号, 若依然找不到,则字符串无效
if(item === ')') {
var _stack = [...stack].reverse();
// 若栈为空,则字符串无效
if(_stack.length === 0) {
stack.push(-1);
break;
}
// 寻找最近的左括号或左星号,都没有,则字符串无效
var index = _stack.indexOf('(') > -1 ? _stack.indexOf('(') : _stack.indexOf('*');
if(index === -1) {
break;
}
// 将最近的左括号或左星号替换为空
stack[stack.length - index -1] = '';
}
}
stack = stack.filter(item => item !== '');
// stack数组情况,可能存在多余的左括号( 和 多余的星号,将(和*相互抵消
for(var j = stack.length - 1; j >= 0; j--) {
if(stack[j] === '(') {
// 检查元素右侧是否存在星号,若存在,则将
var starIndex = stack.indexOf('*',j);
if(starIndex > -1) {
stack[j] = '';
stack[starIndex] = '';
} else {
break;
}
}
}
return stack.join('').replaceAll('*','').length === 0;
} #include <stack>
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param s string字符串
* @return bool布尔型
*/
bool isValidString(string s) {
// write code here
if (s.size() == 0) return true;
// 先清除可以匹配的(),如(*())(()))变成(*))
stack<char> chs;
for (char ch : s) {
if (ch == ')') {
if (chs.empty()) {
return false;
}
else if (chs.top() == '(') {
chs.pop();
}
else {
chs.push(ch);
}
}
else {
chs.push(ch);
}
}
// 如果末尾为(,必非法
if (!chs.empty() && chs.top() == '(') return false;
// 连接剩下的字符串
s = "";
while (!chs.empty()) {
s = chs.top() + s;
chs.pop();
}
return isMatch(s);
}
// 判断字符串是否能够匹配,即*适当转变之后能够匹配()
bool isMatch(string s) {
/**
* 判断是否存在)(的情况,存在则分开字符串分别再次匹配
* 如*)(((*),看似3个(,2个),可以将一个*转变为),但是它非法
* 此时需将*)和(((*)分别判断,前者匹配后者否,所以非法
*/
int pos = -1;
for (int i = 1; i < s.size(); i++) {
if (s[i - 1] == ')' && s[i] == '(') {
pos = i;
break;
}
}
/**
* 不存在)(的情况,直接判断是否匹配,
* 只需(的数量与)的数量差值不大于*的数量,
* 则*可以适当转变(或)使得匹配
*/
if (pos < 0) {
int left = 0, right = 0, mid = 0;
for (char ch : s) {
if (ch == '(') {
left++;
}
else if (ch == ')') {
right++;
}
else if (ch == '*') {
mid++;
}
}
return abs(left - right) <= mid;
}
// 存在)(的情况,分开字符串分别再次匹配,即递归
string left = s.substr(0, pos);
string right = s.substr(pos, s.size() - pos);
return isMatch(left) && isMatch(right);
}
}; function isValidString( s ) {
// write code here
// 根据星号数量和左右括号数量最少的数量的和和左右括号数量最多的数量作比较来淘汰不符合的字符
let leftCount = s.match(/\(/g)?s.match(/\(/g).length:0;
let rightCount = s.match(/\)/g)?s.match(/\)/g).length:0;
let xingCount = s.match(/\*/g)?s.match(/\*/g).length:0;
if(xingCount+Math.min(leftCount,rightCount) < Math.max(leftCount,rightCount)){
return false
}
else{
// 定义三个匹配模式匹配可以成对的括号
let pattern1 = /\((\**)\)/;//中间的括号用于捕获
let pattern2 = /\(\*/;//注意,这里不加g,是为了每次都能从头匹配
let pattern3 = /\*\)/;
while(pattern1.test(s)){
s = s.replace(/\((\**)\)/g,'$1');//$1是捕获的第一个数据
}
while(pattern2.test(s)){
s = s.replace(/\(\*/g,'');
}
while(pattern3.test(s)){
s = s.replace(/\*\)/g,'');
}
if(/^\**$/.test(s)){
return true
}else{
return false
}
}
} class Solution:
def isValidString(self, s: str) -> bool:
low, high = 0, 0 # 维护左括号数量的最小、最大可能值
for c in s:
if c == '(':
low += 1
high += 1
elif c == ')':
if low > 0: # 尽量消耗左括号,减少最小可能
low -= 1
high -= 1 # 右括号必须匹配,最大可能减少
else: # c == '*',三种情况取最优
if low > 0: # * 当右括号,减少最小可能
low -= 1
high += 1 # * 当左括号,增加最大可能
if high < 0: # 右括号过多,直接不合法
return False
return low <= 0 #
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param s string字符串
# @return bool布尔型
#
class Solution:
def isValidString(self , s: str) -> bool:
# write code here
stack=[]
if(len(s)==0):
return True
count=0
for j in range(len(s)):
if(s[j]=='('):
count+=1
elif(s[j]==')'):
count-=1
if(count>=0):
for i in range(len(s)):
if(s[i]=='('):
stack.append(s[i])
if(s[i]==')'):
try:
stack.pop()
except:return False
if(s[i]=='*' and len(stack)!=0 and count!=0):
stack.pop()
count-=1
if(count<0):
for i in range(len(s)):
if(s[i]=='*'and count!=0):
stack.append(s[i])
count+=1
if(s[i]=='('):
stack.append(s[i])
if(s[i]==')'):
try:
stack.pop()
except:return False
if(len(stack)==0):
return True
else:return False 我在调试里面能输出正确值,但是在自测里又不行了,挺神奇
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param s string字符串
* @return bool布尔型
*/
public boolean isValidString (String s) {
if (s.length() == 0) {
return true;
}
LinkedList<Integer> leftStack = new LinkedList<>();
LinkedList<Integer> starStack = new LinkedList<>();
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
if (ch == '(') {
leftStack.push(i);
} else if (ch == '*') {
starStack.push(i);
} else if (ch == ')') {
if (!leftStack.isEmpty()) {
leftStack.pop();
} else if (!starStack.isEmpty()) {
starStack.pop();
} else {
return false;
}
}
}
while (!leftStack.isEmpty() && !starStack.isEmpty()) {
if (leftStack.peek() > starStack.peek()) {
return false;
}
leftStack.pop();
starStack.pop();
}
return leftStack.isEmpty();
}
} #
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param s string字符串
# @return bool布尔型
#
class Solution:
def isValidString(self,s:str) -> bool:
# write code here
class Stack:
def __init__(self) -> None:
self.items = []
def isEmpty(self):
return self.items == []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def size(self):
return len(self.items)
s1 = Stack()
star_list=[]
index, last_index, star_index = 0, 0, 0
pre_index1,pre_index2=0,0
balanced = True
while index < len(s) and balanced:
char = s[index]
if char == '(' :
s1.push(char)
pre_index1=last_index
last_index=max(last_index,index)
elif char == '*':
star_list.append(char)
pre_index2=star_index
star_index=max(star_index,index)
else:
if s1.isEmpty() and star_list == []:
balanced = False
else:
if not s1.isEmpty():
s1.pop()
last_index=pre_index1
else:
star_list.pop()
star_index=pre_index2
index += 1
if s1.isEmpty() and balanced:
return True
elif s1.size()<=len(star_list) and balanced and star_index>=last_index:
return True
else:
return False
*****( 使用出入栈 单向遍历 是由问题的 import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param s string字符串
* @return bool布尔型
*/
public boolean isValidString (String s) {
// write code here
Deque<Integer> stack1 = new ArrayDeque<>();
Deque<Integer> stack2 = new ArrayDeque<>();
for(int i = 0; i < s.length(); i++) {
switch(s.charAt(i)) {
case '(':
stack1.offerLast(i);
break;
case '*':
stack2.offerLast(i);
break;
case ')':
if(!stack1.isEmpty()) {
stack1.pollLast();
} else {
if(stack2.isEmpty()) return false;
stack2.pollLast();
}
break;
}
}
while(!stack1.isEmpty()) {
if(stack2.isEmpty()) break;
if(stack1.getLast() > stack2.getLast()) break;
stack1.pollLast();
stack2.pollLast();
}
return stack1.isEmpty();
}
}