Give a string s
, count the number of non-empty (contiguous) substrings that have the same number of 0's and 1's, and all the 0's and all the 1's in these substrings are grouped consecutively.
Substrings that occur multiple times are counted the number of times they occur.
Example 1:
Input: "00110011" Output: 6 Explanation: There are 6 substrings that have equal number of consecutive 1's and 0's: "0011", "01", "1100", "10", "0011", and "01".
Notice that some of these substrings repeat and are counted the number of times they occur.
Also, "00110011" is not a valid substring because all the 0's (and 1's) are not grouped together.
Example 2:
Input: "10101" Output: 4 Explanation: There are 4 substrings: "10", "01", "10", "01" that have equal number of consecutive 1's and 0's.
Note:
s.length
will be between 1 and 50,000.s
will only consist of "0" or "1" characters.
本题目中就是计算相邻的0和相邻的1中,1和0个数相同的子串
本来有一个非常笨的方法,就是两个循环,
i 一个用来记录当前字符指向的位置为0/1,
j 另外一个用来计算后面为1/0的个数,当个数相同时,count++,不够的话,i++,向下移动一位,继续查找
这种方法得到的结果可以通过,但是对于字符串非常大的,会有Time Limit Exceeded
AC不通过
换了一种想法,借助于KMP算法中的next数组的思想,也定义一个help数组,用来存放当前字符以及后面与它相同字符的个数
然后再遍历字符串,当当前help[index]的字符 <= 下一个和它不同的字符的help[i] 则符合题意,count++; 然后index++,继续计算
class Solution { public int countBinarySubstrings(String s) { if(s == null || s.length() == 0) return 0; int[] help = new int[s.length()]; int index = 0; int i = 0; while(i < s.length()){ int count = 0; char ch = s.charAt(index); while(i < s.length() && ch == s.charAt(i)){ count++; i++; } while(index < i){ help[index++] = count--; } } int res = 0; i = 0; index = 0; while(i < help.length){ char ch = s.charAt(index); while(i < s.length() && ch == s.charAt(i)){ i++; } while(i < help.length && index < i){ if(help[index] <= help[i]) { res++; } index++; } } return res; } }
但还是非常麻烦。
在讨论区看到一种非常简单的方法用来表示help数组,就是直接用一个值pre来记录前面(0/1)的值的个数,然后用cur来记录当前遍历到的(1/0)位置的值的个数(注意pre和cur指向的值是相反的)。当pre >= cur 时,则前面的0可以和后面的1符合要求,然后cur继续向后移动,继续判断。当cur移动到不等的地方时,pre则指向当前cur指向的位置的值的个数,cur继续重复上面的过程。
public int countBinarySubstrings(String s) {
int prevRunLength = 0, curRunLength = 1, res = 0;
for (int i=1;i<s.length();i++) {
if (s.charAt(i) == s.charAt(i-1)) curRunLength++;
else {
prevRunLength = curRunLength;
curRunLength = 1;
}
if (prevRunLength >= curRunLength) res++;
}
return res;
}
说到底就是判断相邻的 0 和 1 哪个比较少,则res += 较少的个数。
public int countBinarySubstrings(String s) {
int cur = 1, pre = 0, res = 0;
for (int i = 1; i < s.length(); i++) {
if (s.charAt(i) == s.charAt(i - 1)) cur++;
else {
res += Math.min(cur, pre);
pre = cur;
cur = 1;
}
}
return res + Math.min(cur, pre);
}