LWC 54:696. Count Binary Substrings
传送门:696. Count Binary Substrings
Problem:
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.
思路1:
实际上,对于每一位都只可能出现1次合法答案或者0次答案。因为如果存在第二个合法答案,一定不符合group的条件,比如“0011”和“1100”是无法合并在一块构成新的合法答案。
代码如下:
public int countBinarySubstrings(String s) {
int n = s.length();
char[] cs = s.toCharArray();
int cnt = 0;
for (int i = 1; i < n; ++i){
if (group(cs, i)) cnt ++;
}
return cnt;
}
boolean group(char[] cs, int j){
int cnt = 1;
int pre = cs[j] - '0';
j --;
while (j >= 0 && cs[j] - '0' == pre) {
cnt ++;
j --;
}
while (j >= 0 && cs[j] - '0' != pre && cnt != 0) {
cnt --;
j --;
}
return cnt == 0;
}
思路2:
单纯的来看”00111”,它的个数为min(0出现的次数,1出现的次数),所以代码如下:(注意交替更新)
public int countBinarySubstrings(String s) {
int n = s.length();
char[] cs = s.toCharArray();
int now = cs[0] - '0';
int cnt = 0;
int ans = 0;
int lst = 0;
for (int i = 0; i < n; ++i) {
if (now != cs[i]) {
ans += Math.min(cnt, lst);
lst = cnt;
cnt = 1;
now = cs[i];
}
else {
cnt ++;
}
}
ans += Math.min(cnt, lst);
return ans;
}
思路3:
采用map,累加和,把0011映射成数组{-1,-1,1,1},再求累加和得到{0,-1,-2,-1,0},所以出现-1的两个位置组成的subSeqence一定是可能的候选值,再判断是否符合group。
代码如下:
public int countBinarySubstrings(String s) {
int n = s.length();
char[] cs = s.toCharArray();
int[] num = new int[n];
for (int i = 0; i < n; ++i) {
num[i] = cs[i] == '0' ? - 1 : 1;
}
int[] sum = new int[n + 1];
for (int i = 0; i < n; ++i) {
sum[i + 1] = sum[i] + num[i];
}
Map<Integer, Integer> map = new HashMap<>();
map.put(0, 0);
int cnt = 0;
for (int i = 1; i <= n; ++i) {
if (map.containsKey(sum[i])) {
if (group(cs, map.get(sum[i]), i - 1)) cnt++;
}
map.put(sum[i], i);
}
return cnt;
}
boolean group(char[] cs, int i, int j) {
int prev = cs[i] - '0';
int n = j - i + 1;
for (int k = 1; k < n / 2; ++k) {
if (prev != cs[k + i] - '0') return false;
}
return true;
}