传统思路
- 嵌套循环,找出每个字符串的连续次数,并记录
- 看似时间复杂度是O(n^2)
- 但实际时间复杂度是多少?---O(n) 因为有跳步

嵌套循环思路代码:
interface IRes {
char: string
length: number
}
function findContinuousChar1(str: string): IRes {
const res: IRes = {
char: '',
length: 0,
}
const length = str.length
if (length === 0) return res
let tempLength = 0 // 临时记录当前连续字符的长度
for (let i = 0
tempLength = 0 // 重置
for (let j = i
if (str[i] === str[j]) {
tempLength++
}
if (str[i] !== str[j] || j === length - 1) {
// 不相等,或者已经到了最后一个元素,要去判断最大值
if (tempLength > res.length) {
res.char = str[i]
res.length = tempLength
}
if (i < length - 1) {
i = j - 1 // 跳步
}
break
}
}
}
return res
}
// 功能测试
const str = 'aabbcccddeeee11223'
console.info(findContinuousChar1(str))
结果:

双指针思路 O(n)
- 定义指针i和j。j不动,i继续移动
- 如果i和j的值一直相等,则i继续移动
- 指导i和j的值不相等,记录处理,让j追上i。继续第一步
function findContinuousChar2(str: string): IRes {
const res: IRes = {
char: '',
length: 0,
}
const length = str.length
if (length === 0) return res
let tempLength = 0 // 临时记录当前连续字符的长度
let i = 0
let j = 0
for (
if (str[i] === str[j]) {
tempLength++
}
if (str[i] !== str[j] || i === length - 1) {
// 不相等, 或者 i 到了字符串的末尾
if (tempLength > res.length) {
res.char = str[j]
res.length = tempLength
}
tempLength = 0 // reset
if (i < length - 1) {
j = i // 让j 追上i
i-- // 细节
}
}
}
return res
}
// 功能测试
const str = 'aabbcccddeeee11223'
console.info(findContinuousChar2(str))
网络上其他方式
- 正则表达式-效率非常低,慎用
- 累计各个元素的连续长度,最后求最大值 --- 徒增空间复杂度
- 算法题尽量用“低级”代码,慎用语法糖或者高级API
const str1 = '100abc'
const reg = /^\d+/
console.time('reg')
for (let i = 0; i < 100 * 10000; i++) {
reg.test(str1)
}
console.timeEnd('reg')
console.time('indexOf')
for (let i = 0; i < 100 * 10000; i++) {
str1.indexOf('100')
}
console.timeEnd('indexOf')
划重点
- 要注意实际复杂度,不要被代码表面迷惑
- 双指针常用于解决嵌套循环
- 算法题慎用正则(工作中可用)