对一个规定的字符串,字符串只包含(和),找出最大的括号系列;
例1
输入:
"(()"
返回值:
2
例2
输入:
"(())()"
返回值:
6
这个题给我感觉是像玩过的一款游戏,比如消消乐,所以我的思路是发现匹配的(),把它消成0,
如(())(),先消为(00)(),
如果中间都是0,那么整个两端肯定匹配,如(00)一定匹配,可以再次消为0000,
如果一个字符的前面为000,那么连在一起也一定匹配,如0000(),也是可以匹配的括号系列,可以消为000000
所以(())(),依次消为
(00)()
0000()
0000000
最大长度,其实就是最大的包含0的连续子串
很明显,要实现上述的消消乐,必须借助栈来实现,一个原栈、一个零栈,
遍历原字符串,第一次第一个字符先入原栈
当字符串匹配时,变成0,压入零栈,
发现不匹配时,记录此时的零栈的长度,更新最大值,同时将零栈的0全部压回到原栈中,字符压入原栈
当原栈顶元素为0时,将连续的0压回到零栈,直到栈顶不是0为止。
上述过程,发现不匹配时,只要记录零栈的最大长度,即找到最大的括号长度
代码如下:
import java.util.Stack;
/**
* 匹配长度最大的()系列
* @author ssj
*
*/
public class FindMaxKuohao {
public static void main(String[] args) {
String str="((()()())()";
//String str="(())";
Stack<Character> stk=new Stack<Character>();
Stack<Character> zeroStk=new Stack<Character>();//中间栈
int k=0;
int maxLength=0;//最大长度
int tempLength=0;//最大长度中间变量
int maxEndIndex=-1;//最大子串的结束位置
stk.push(str.charAt(k ));
while(k<str.length()) {
if(!stk.isEmpty()&&ismatch(stk.peek(), str.charAt(k))) {
//如果匹配了,匹配的()变成0,入栈到temp中
stk.pop();//匹配()后消失
zeroStk.push('0');
zeroStk.push('0');
//后面有0,本次又能匹配,那么整个串肯定是匹配的,继续消长
while(!stk.isEmpty()&&stk.peek()=='0') {
zeroStk.push(stk.pop());
}
}else {
//如果发现不匹配了,将当前已经匹配的系列倒回到原栈中
tempLength=zeroStk.size();
if(tempLength>maxLength) {
maxLength=tempLength;
maxEndIndex=k-1;
}
while(!zeroStk.isEmpty()) {
stk.push(zeroStk.pop());
}
stk.push(str.charAt(k));
}
k ;
}
//计算连续的k字符的长度,最后一次,k=str.length 有可能全部匹配,没有回原栈,zeroStk有值
if(maxLength<zeroStk.size()) {
maxLength=zeroStk.size();
maxEndIndex=k-1;
}
System.out.println("原字符串:" str);
System.out.println("最大匹配长度:" maxLength);
if(maxEndIndex>=0) {
System.out.println("最大匹配位置为:" (maxEndIndex-maxLength 1) "," maxEndIndex);
System.out.println("最大匹配子串:" str.substring(maxEndIndex-maxLength 1, maxEndIndex 1));
}
}
/**
* 判断两个字符是否匹配
* @param a
* @param b
* @return
*/
public static boolean ismatch(Character a,Character b ) {
if(a=='('&&b==')') {
return true;
}
if(b=='('&&a==')') {
return true;
}
return false;
}
}
运行结果