[LeetCode]696. 计数二进制子串(java实现)
1. 题目
2. 读题(需要重点注意的东西)
本题的思路难,但实现简单,现对思路进行分析如下:
- 子串里的0、1都要是连续且分布于字符串两边,如00001111,如00110011这样交叉是不行的
- s = “00110011”—> 2 2 2 2 ,这里两个相邻的数一定代表的是两种不同的字符的个数;若s = "1110001010“ — > 3 3 1 1 1 1。
- 基本思路:先统计连续的0和1分别有多少个,如:00110011,得到2 2 2 2 ;在2 2 2 2 中的任意相邻两个数字,取小的一个加起来,就是2+2+2+2 = 8;
- 为什么要取小的加起来?
这是因为结果的子字符串是由小的决定的,如0001111,可以分解为子字符串 01,0011,000111;如110,可以分解为符合题意的子字符串10。 - 因此得到最终解题的思路:用pre记录前一个数出现的次数,用cur记录现在的数字出现的次数,当数字变化时,取min(pre,cur)加到最终的结果result中
3. 解法
解法:
class Solution {
// 基本思路:先统计连续的0和1分别有多少个,如:111100011000,得到4323;在4323中的任意相邻两个数字,取小的一个加起来,就是3+2+2 = 7
// 进阶:用pre记录前一个数出现的次数,用cur记录现在的数字出现的次数,当数字变化时,取min(pre,cur)加到最终的结果result中
// 实现简单,思路难
public int countBinarySubstrings(String s) {
int pre = 0, cur = 1;
int result = 0;
s = s.concat("a");
for(int i = 0; i < s.length()-1; i++){
if(s.charAt(i) == s.charAt(i+1)){
cur++;
}
if(s.charAt(i) != s.charAt(i+1)){
if(pre != 0){
result = result + Math.min(pre , cur);
pre = cur;
cur = 1;
}else{
pre = cur;
cur = 1;
}
}
}
return result;
}
}
部分代码解释可在Java数据结构—String(字符串及其常用操作)中得到介绍