LeetCode 434. 字符串中的单词数
题目描述

题意分析
这里的“单词”指一段连续的非空格字符,只由普通空格
' '分隔,不要求内容都是字母。数字或标点只要没有被空格隔开,就仍属于同一段。需要返回片段数量,不需要保存片段内容。因此无需实际切割字符串,只要识别每段开始的位置。
解法:一次扫描计数
核心思路
[!blue]
一个位置是片段开头,需要同时满足两个条件:当前字符不是空格;当前位置在串首,或者前一个字符是空格。后一个条件表示扫描刚从分隔区域进入了一段内容。
每个非空格片段的首字符都符合这个条件,而片段内部字符的前一位仍是非空格,不会再次计数。反过来,任何符合条件的位置都确实开始一个新片段。因此段首与片段一一对应,累计段首数量就是答案。
计数在开头就已完成,最后一段后面有没有空格都不会影响结果。连续空格和前后空格因为自身不满足“当前非空格”,也都不会多贡献计数。
解题步骤
- 初始化计数
answer = 0,从左到右扫描字符串。- 若当前位置非空格,继续检查它是否位于串首,或前一个字符是否为空格。
- 满足条件就将计数加一,扫描结束后返回总数。
串首用
i == 0单独覆盖,通过逻辑或的短路求值避免读取负下标。空串不进入循环,全空格字符串没有段首,两者都返回零。
代码实现
class Solution {
public int countSegments(String s) {
int answer = 0;
for (int i = 0; i < s.length(); i++) {
// 当前非空格且前面是分隔符或串首,才开始一个新片段。
if (s.charAt(i) != ' ' && (i == 0 || s.charAt(i - 1) == ' ')) {
answer++;
}
}
return answer;
}
}
func countSegments(s string) int {
answer := 0
for i := range s {
// 当前非空格且前面是分隔符或串首,才开始一个新片段。
if s[i] != ' ' && (i == 0 || s[i-1] == ' ') {
answer++
}
}
return answer
}
复杂度分析
- 时间复杂度:$O(L+1)$,L 为字符串长度,一次扫描。
- 空间复杂度:$O(1)$,不创建分割数组。
关键点总结
[!green]
- 计数对象是段首,不是非空格字符本身。
- 串首条件通过短路判断保护前驱访问。
- 连续、前导和尾随空格都由同一条件处理。
易错点总结
[!yellow]
- 空格数量加一:连续或前导空格会多算。
- 每个非空格字符都加一:统计成字符数。
- 只在空格处结算又不补末段:最后没有空格时漏计。
- 把标点当成分隔符:改变了题目对片段的定义。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 58. 最后一个单词的长度 | 简单 | 同样识别空格分隔的非空单词段,原题只计算最后一段长度。 |
| 151. 反转字符串中的单词 | 中等 | 单词边界识别可复用,原题还把所有单词按逆序输出。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!