题目描述
思路解析动画文字版
记牢一句话:相邻两段贡献 min(前段长, 本段长),全部加起来。下面每一帧都在套它。
先看整串八个字符。接下来从左往右扫,把挨在一起、字符相同的归成同一段。
第 1 段开始:下标 0 是字符 "0",本段长度先记成 1,把它涂绿。
下标 1 还是 "0",和前一个相同,归进这一段,本段长度变成 2。
下一个字符变了,第 1 段到此封口,"0" 一共连续 2 个。现在该和前一段配对了。
它前面还没有任何段,pre = 0,配不出子串,本段贡献 0,ans 仍是 0。接着把本段长度 2 存进 pre,留给下一段配对。
第 2 段开始:下标 2 是字符 "1",本段长度先记成 1,把它涂绿。
下标 3 还是 "1",和前一个相同,归进这一段,本段长度变成 2。
下一个字符变了,第 2 段到此封口,"1" 一共连续 2 个。现在该和前一段配对了。
前一段长 pre = 2,本段长 run = 2,两段能拼出 min(2, 2) = 2 个合法子串。ans 从 0 累加到 2,再把 pre 更新成 2。
第 3 段开始:下标 4 是字符 "0",本段长度先记成 1,把它涂绿。
下标 5 还是 "0",和前一个相同,归进这一段,本段长度变成 2。
下一个字符变了,第 3 段到此封口,"0" 一共连续 2 个。现在该和前一段配对了。
前一段长 pre = 2,本段长 run = 2,两段能拼出 min(2, 2) = 2 个合法子串。ans 从 2 累加到 4,再把 pre 更新成 2。
第 4 段开始:下标 6 是字符 "1",本段长度先记成 1,把它涂绿。
下标 7 还是 "1",和前一个相同,归进这一段,本段长度变成 2。
已经扫到末尾,第 4 段到此封口,"1" 一共连续 2 个。现在该和前一段配对了。
前一段长 pre = 2,本段长 run = 2,两段能拼出 min(2, 2) = 2 个合法子串。ans 从 4 累加到 6,再把 pre 更新成 2。
整串扫完,分成了四段,长度依次是 2、2、2、2。蓝色就是已经数过的段。
四段产生三对相邻段,每对取较短段:min(2,2) 三次,每次给 2 个,加起来 6 个。
把所有相邻段的 min 累加,得到答案 6,和题目给的输出对上了。
边界先想清:空串、整串同字符、最短的一对。
面试重点:认出「分组 + 在段长上运算」,并能压到只用两个变量。
参考代码
from __future__ import annotationsfrom typing import *from collections import *from functools import *from itertools import *from math import *from heapq import *from bisect import *class Solution: def countBinarySubstrings(self, s: str) -> int: n = len(s) ans = i = 0 pre = 0 while i < n: j = i + 1 while j < n and s[j] == s[i]: j += 1 cur = j - i ans += min(pre, cur) pre = cur i = j return ans复杂度
- 时间:O(n),i 与 j 都只单向走一遍,每个字符看一次
- 空间:O(1),只用 pre、cur、ans 几个变量
易错点
面试追问把动画讲成自己的话
追问能不能不存所有段长,只用两个变量?
追问这题和「最长连续段」类题是一个套路吗?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
字符的最短距离
LeetCode 821 · 简单 · 沿着 双指针套路 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题