LeetCode统计单字符子串代码中S=' '+S+' '的作用是什么?
题目核心规律
给定字符串s,返回仅包含单一不同字符的子串的数量。
连续k个相同字符可以贡献的符合要求的子串总数是 k*(k+1)/2,等价于1+2+...+k,也就是遍历到连续段的第i个字符时,累加i即可得到该连续段的总贡献。
代码整体逻辑
这段代码的核心思路是:遍历原字符串的每一个位置,统计以当前位置为结尾的、全字符相同的子串数量,累加到总结果中:
- 遇到和前一个字符相同的情况,当前连续长度
count加1,这个值就是当前位置能贡献的符合要求的子串数 - 遇到和前一个字符不同的情况,重置连续长度
count为1,重新计数
我们以输入aaaba为例,累加过程为1(第一个a)+2(第二个a)+3(第三个a)+1(b)+1(最后一个a)=8,和题目要求的输出一致。
首尾拼接空格的作用
前导空格的核心作用
如果不添加前导空格,遍历从原字符串的第一个字符(索引0)开始时,不存在i-1的索引,会触发越界错误,你必须额外写代码单独处理第一个字符的边界情况,比如手动给total加1、初始化count=1再从索引1开始遍历。
添加前导空格后,原字符串的第一个字符的索引变为1,此时S[i-1]是空格,必然和原字符串的第一个字符不同,所以第一次循环会自动将count设为1,不需要额外的边界处理代码,逻辑更统一。
尾部空格的作用
尾部空格实际不会参与遍历判断:添加前后空格后总字符串长度为原长度+2,循环范围是range(1, len(S)-1),刚好覆盖原字符串的所有字符,不会遍历到尾部的空格。这种写法属于对称式的偏移处理,不需要手动计算原字符串的长度偏移,代码可读性更高。当然你也可以选择只加前导空格,循环写为range(1, len(S)),运行效果完全一致。
无空格版本的对照写法
如果不使用拼接空格的技巧,代码需要单独处理首字符边界,写法如下:
def countLetters(self, S: str) -> int: if not S: return 0 total, count = 1, 1 for i in range(1, len(S)): if S[i] != S[i-1]: count = 1 else: count += 1 total += count return total
对比可以看出,拼接空格的写法省掉了空串判断、首字符初始化的额外逻辑,代码更简洁,不容易出现边界bug。
内容的提问来源于stack exchange,提问作者one_random_python_learner

