Description:
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组成的字串,返回结果数;
解法一(超时):对字符串进行遍历,找出每一次的连续0或者1后,看是否可以再后面连续相同长度的字符串中找到匹配的连续0或者1;
Java
class Solution {
public int countBinarySubstrings(String s) {
int cnt = 0;
for (int i = 0; i < s.length() - 1; i++) {
int index = i;
String temp = null;
while (index < s.length() && s.charAt(i) == s.charAt(index)) index++;
temp = s.substring(Math.min(index, s.length() - 1),
Math.min(index + index - i, s.length()));
cnt = temp.length() == (index - i) && isSame(temp) ? cnt + 1 : cnt;
}
return cnt;
}
private boolean isSame(String s) {
for (int i = 0; i < s.length() - 1; i++) {
if (s.charAt(i) != s.charAt(i + 1)) {
return false;
}
}
return true;
}
}
解法二:每一次都要从当前位置重新遍历寻找连续的0或者1花费的时间代价太高了;考虑字符串“000111”一共有“000111”、“0011”、“01”三种组合方式,那么我们就可以将每个连续的0或者1的长度存储起来,连续的0和1之间最短的那个长度就是所有的组合方式;
Java
class Solution {
public int countBinarySubstrings(String s) {
int result = 0;
List<Integer> group = new ArrayList<>();
int len = 1;
for (int i = 0; i < s.length() - 1; i++) {
if (s.charAt(i) == s.charAt(i + 1)) {
len++;
} else {
group.add(len);
len = 1;
}
}
group.add(len);
for (int i = 0; i < group.size() - 1; i++) {
result += Math.min(group.get(i), group.get(i + 1));
}
return result;
}
}
解法三:针对第二种要保存每一个连续的0或1的长度来说,我们可以只保存前一个和当前的连续0或者1的长度,这样得到的组合数是Math.min(前一个连续0或者1的长度, 当前连续0或者1的长度);
Java
class Solution {
public int countBinarySubstrings(String s) {
int pre = 0;
int cur = 1;
int result = 0;
for (int i = 0; i < s.length() - 1; i++) {
if (s.charAt(i) == s.charAt(i + 1)) {
cur++;
} else {
result += Math.min(pre, cur);
pre = cur;
cur = 1;
}
}
result += Math.min(pre, cur);
return result;
}
}