题目描述
给你一个仅由 0 和 1 组成的二进制字符串 s 。
如果子字符串中 所有的 0 都在 1 之前 且其中 0 的数量等于 1 的数量,则认为 s 的这个子字符串是平衡子字符串。请注意,空子字符串也视作平衡子字符串。
返回 s 中最长的平衡子字符串长度。
子字符串是字符串中的一个连续字符序列。
示例 1:
输入:s = “01000111”
输出:6
解释:最长的平衡子字符串是 “000111” ,长度为 6 。
示例 2:
输入:s = “00111”
输出:4
解释:最长的平衡子字符串是 “0011” ,长度为 4 。
示例 3:
输入:s = “111”
输出:0
解释:除了空子字符串之外不存在其他平衡子字符串,所以答案为 0 。
提示:
1 <= s.length <= 50
‘0’ <= s[i] <= ‘1’
package leetcode;
public class p2609 {
public static void main(String[] args) {
}
/**
*思路:遍历字符串,当值为字符0时让ct0++,为字符1时让ct1++,并用flag标识当前时连续的0还是1,
* 同时处理下一个0开始的子串或是以1到达末尾的情况
* 时间复杂度O(n) 空间复杂度O(1)
*/
public static int findTheLongestBalancedSubstring(String s) {
int maxLen=0;
int ct0=0;
int ct1=0;
int flag=0;
for (int i=0;i<s.length();i++){
if (flag==0 && s.charAt(i)=='0'){
ct0++;
}else if (flag==0 && s.charAt(i)=='1'){
flag=1;
ct1++;
if (i== s.length()-1){
int min=Math.min(ct0,ct1);
maxLen=Math.max(maxLen,min);
}
} else if (flag==1 && s.charAt(i)=='1') {
ct1++;
if (i== s.length()-1){
int min=Math.min(ct0,ct1);
maxLen=Math.max(maxLen,min);
}
} else if (flag==1 && s.charAt(i)=='0') {
int min=Math.min(ct0,ct1);
maxLen=Math.max(maxLen,min);
ct0=ct1=0;
flag=0;
ct0++;
}
}
return maxLen*2;
}
// 优化:发现当字符值为1的两个条件分支可以合并,使消耗内存减少了
public static int findTheLongestBalancedSubstring2(String s) {
int maxLen=0;
int ct0=0;
int ct1=0;
int flag=0;
for (int i=0;i<s.length();i++){
if (flag==0 && s.charAt(i)=='0'){
ct0++;
}else if (s.charAt(i)=='1'){
flag=1;
ct1++;
if (i== s.length()-1){
int min=Math.min(ct0,ct1);
maxLen=Math.max(maxLen,min);
}
} else if (flag==1 && s.charAt(i)=='0') {
int min=Math.min(ct0,ct1);
maxLen=Math.max(maxLen,min);
ct0=ct1=0;
flag=0;
ct0++;
}
}
return maxLen*2;
}
// 看了题解之后写的更优雅的代码
// 但是这里消耗的内存却比上面优化的代码多,是因为while循环会占用更大的内存的原因吗?
public static int findTheLongestBalancedSubstring3(String s) {
int n=s.length(),index=0,maxLen=0;
while (index<n){
int ct0=0,ct1=0;
while (index<n && s.charAt(index)=='0' && ++ct0>0) index++;
while (index<n && s.charAt(index)=='1' && ++ct1>0) index++;
maxLen=Math.max(maxLen,Math.min(ct0,ct1)*2);
}
return maxLen;
}
}
总结:对于这种连续的1和0而且一定是0在前1在后,可以不使用flag标志位而直接用while循环统计其长度。