加载中...
696-计数二进制子串(Count Binary Substrings)
发表于:2021-12-03 | 分类: 简单
字数统计: 1.6k | 阅读时长: 8分钟 | 阅读量:

原文链接: https://leetcode-cn.com/problems/count-binary-substrings

英文原文

Give a binary string s, return the number of non-empty 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: s = "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: s = "10101"
Output: 4
Explanation: There are 4 substrings: "10", "01", "10", "01" that have equal number of consecutive 1's and 0's.

 

Constraints:

  • 1 <= s.length <= 105
  • s[i] is either '0' or '1'.

中文题目

给定一个字符串 s,计算具有相同数量 0 和 1 的非空(连续)子字符串的数量,并且这些子字符串中的所有 0 和所有 1 都是连续的。

重复出现的子串要计算它们出现的次数。

 

示例 1 :

输入: "00110011"
输出: 6
解释: 有6个子串具有相同数量的连续1和0:“0011”,“01”,“1100”,“10”,“0011” 和 “01”。

请注意,一些重复出现的子串要计算它们出现的次数。

另外,“00110011”不是有效的子串,因为所有的0(和1)没有组合在一起。

示例 2 :

输入: "10101"
输出: 4
解释: 有4个子串:“10”,“01”,“10”,“01”,它们具有相同数量的连续1和0。

 

提示:

  • s.length 在1到50,000之间。
  • s 只包含“0”或“1”字符。

通过代码

高赞题解

方法一:按字符分组

思路与算法

我们可以将字符串 $s$ 按照 $0$ 和 $1$ 的连续段分组,存在 $\textit{counts}$ 数组中,例如 $s = 00111011$,可以得到这样的 $\textit{counts}$ 数组:$\textit{counts} = {2, 3, 1, 2}$。

这里 $\textit{counts}$ 数组中两个相邻的数一定代表的是两种不同的字符。假设 $\textit{counts}$ 数组中两个相邻的数字为 $u$ 或者 $v$,它们对应着 $u$ 个 $0$ 和 $v$ 个 $1$,或者 $u$ 个 $1$ 和 $v$ 个 $0$。它们能组成的满足条件的子串数目为 $\min { u, v }$,即一对相邻的数字对答案的贡献。

我们只要遍历所有相邻的数对,求它们的贡献总和,即可得到答案。

不难得到这样的实现:

[sol0-C++]
class Solution { public: int countBinarySubstrings(string s) { vector<int> counts; int ptr = 0, n = s.size(); while (ptr < n) { char c = s[ptr]; int count = 0; while (ptr < n && s[ptr] == c) { ++ptr; ++count; } counts.push_back(count); } int ans = 0; for (int i = 1; i < counts.size(); ++i) { ans += min(counts[i], counts[i - 1]); } return ans; } };
[sol0-Java]
class Solution { public int countBinarySubstrings(String s) { List<Integer> counts = new ArrayList<Integer>(); int ptr = 0, n = s.length(); while (ptr < n) { char c = s.charAt(ptr); int count = 0; while (ptr < n && s.charAt(ptr) == c) { ++ptr; ++count; } counts.add(count); } int ans = 0; for (int i = 1; i < counts.size(); ++i) { ans += Math.min(counts.get(i), counts.get(i - 1)); } return ans; } }
[sol0-JavaScript]
var countBinarySubstrings = function(s) { const counts = []; let ptr = 0, n = s.length; while (ptr < n) { const c = s.charAt(ptr); let count = 0; while (ptr < n && s.charAt(ptr) === c) { ++ptr; ++count; } counts.push(count); } let ans = 0; for (let i = 1; i < counts.length; ++i) { ans += Math.min(counts[i], counts[i - 1]); } return ans; };
[sol0-Golang]
func countBinarySubstrings(s string) int { counts := []int{} ptr, n := 0, len(s) for ptr < n { c := s[ptr] count := 0 for ptr < n && s[ptr] == c { ptr++ count++ } counts = append(counts, count) } ans := 0 for i := 1; i < len(counts); i++ { ans += min(counts[i], counts[i-1]) } return ans } func min(x, y int) int { if x < y { return x } return y }
[sol0-C]
int countBinarySubstrings(char* s) { int n = strlen(s); int counts[n], counts_len = 0; memset(counts, 0, sizeof(counts)); int ptr = 0; while (ptr < n) { char c = s[ptr]; int count = 0; while (ptr < n && s[ptr] == c) { ++ptr; ++count; } counts[counts_len++] = count; } int ans = 0; for (int i = 1; i < counts_len; ++i) { ans += fmin(counts[i], counts[i - 1]); } return ans; }

这个实现的时间复杂度和空间复杂度都是 $O(n)$。

对于某一个位置 $i$,其实我们只关心 $i - 1$ 位置的 $\textit{counts}$ 值是多少,所以可以用一个 $\textit{last}$ 变量来维护当前位置的前一个位置,这样可以省去一个 $\textit{counts}$ 数组的空间。

代码

[sol1-C++]
class Solution { public: int countBinarySubstrings(string s) { int ptr = 0, n = s.size(), last = 0, ans = 0; while (ptr < n) { char c = s[ptr]; int count = 0; while (ptr < n && s[ptr] == c) { ++ptr; ++count; } ans += min(count, last); last = count; } return ans; } };
[sol1-Java]
class Solution { public int countBinarySubstrings(String s) { int ptr = 0, n = s.length(), last = 0, ans = 0; while (ptr < n) { char c = s.charAt(ptr); int count = 0; while (ptr < n && s.charAt(ptr) == c) { ++ptr; ++count; } ans += Math.min(count, last); last = count; } return ans; } }
[sol1-JavaScript]
var countBinarySubstrings = function(s) { let ptr = 0, n = s.length, last = 0, ans = 0; while (ptr < n) { const c = s.charAt(ptr); let count = 0; while (ptr < n && s.charAt(ptr) === c) { ++ptr; ++count; } ans += Math.min(count, last); last = count; } return ans; };
[sol1-Golang]
func countBinarySubstrings(s string) int { var ptr, last, ans int n := len(s) for ptr < n { c := s[ptr] count := 0 for ptr < n && s[ptr] == c { ptr++ count++ } ans += min(count, last) last = count } return ans } func min(x, y int) int { if x < y { return x } return y }
[sol1-C]
int countBinarySubstrings(char* s) { int ptr = 0, n = strlen(s), last = 0, ans = 0; while (ptr < n) { char c = s[ptr]; int count = 0; while (ptr < n && s[ptr] == c) { ++ptr; ++count; } ans += fmin(count, last); last = count; } return ans; }

复杂度分析

  • 时间复杂度:$O(n)$。
  • 空间复杂度:$O(1)$。

统计信息

通过次数 提交次数 AC比率
54006 85290 63.3%

提交历史

提交时间 提交结果 执行时间 内存消耗 语言

相似题目

题目 难度
字符串的编码与解码 中等
上一篇:
695-岛屿的最大面积(Max Area of Island)
下一篇:
697-数组的度(Degree of an Array)
本文目录
本文目录