TypeScript字符串处理实战:用slice、substring和replace解决5个高频算法题
字符串处理是算法面试中的常客,也是TypeScript开发者必须掌握的核心技能。不同于单纯记忆API用法,真正的挑战在于如何将这些基础方法组合运用,解决实际问题。本文将手把手带你用slice、substring和replace三大核心API,破解5道高频算法题。
1. 反转字符串:巧用slice的负索引
反转字符串是入门级的算法题,但解法却能体现对字符串API的理解深度。先看题目要求:
给定字符串"algorithm",输出反转后的结果"mhtirogla"
传统思路可能会用循环逆序拼接,但TypeScript的slice配合负索引可以更优雅地实现:
function reverseString(str: string): string { return str.split('').reverse().join(''); }不过这种方法需要创建数组,内存效率不高。更优解是利用slice的负索引特性:
function reverseString(str: string): string { let result = ''; for (let i = str.length - 1; i >= 0; i--) { result += str.slice(i, i + 1); } return result; }性能对比:
| 方法 | 时间复杂度 | 空间复杂度 |
|---|---|---|
| 数组反转 | O(n) | O(n) |
| slice拼接 | O(n) | O(1) |
2. 回文判断:substring的对称切割
判断回文字符串时,substring的区间切割能力大显身手。题目示例:
输入"racecar",返回true;输入"typescript",返回false
关键点在于比较首尾对称字符。substring比slice更适合这种精确位置切割:
function isPalindrome(str: string): boolean { const mid = Math.floor(str.length / 2); for (let i = 0; i < mid; i++) { const left = str.substring(i, i + 1); const right = str.substring(str.length - 1 - i, str.length - i); if (left !== right) return false; } return true; }优化技巧:
- 提前终止:发现不匹配立即返回
- 忽略大小写:先统一转小写
str.toLowerCase() - 去除非字母数字:配合
replace(/[^a-z0-9]/g, '')
3. 字符串压缩:replace的正则威力
字符串压缩是LeetCode第443题,要求统计连续相同字符个数。例如:
输入"aaabbbcc",输出"a3b3c2"
replace配合正则表达式能简洁地处理这种模式替换:
function compressString(str: string): string { return str.replace(/([a-z])\1*/g, (match, p1) => { return p1 + (match.length > 1 ? match.length : ''); }); }正则分解:
([a-z]):捕获单个字母\1*:匹配后续相同字符- 回调函数:拼接字符和出现次数
边界情况处理:
| 输入 | 预期输出 | 处理逻辑 |
|---|---|---|
| "a" | "a" | 长度1时不添加数字 |
| "aa" | "a2" | 长度>1时添加计数 |
| "aab" | "a2b" | 混合情况分段处理 |
4. 模板替换:replace的进阶用法
实际开发中常需要处理模板字符串替换。例如:
将"Hello {name}"中的{name}替换为"TypeScript"
replace的回调函数形式可以支持复杂替换逻辑:
function renderTemplate(template: string, data: Record<string, string>): string { return template.replace(/\{(\w+)\}/g, (match, key) => { return data[key] || match; }); } // 使用示例 const result = renderTemplate('Hello {name}', { name: 'TypeScript' }); console.log(result); // 输出:Hello TypeScript扩展功能:
- 嵌套对象:支持
user.name格式 - 默认值:未匹配时返回预设值
- 过滤器:添加
|upper等格式处理
5. 最长公共前缀:substring的渐进裁剪
LeetCode第14题要求找出字符串数组的最长公共前缀。例如:
输入["flower","flow","flight"],输出"fl"
substring的精确裁剪特性非常适合这种渐进式比较:
function longestCommonPrefix(strs: string[]): string { if (strs.length === 0) return ''; let prefix = strs[0]; for (let i = 1; i < strs.length; i++) { while (strs[i].indexOf(prefix) !== 0) { prefix = prefix.substring(0, prefix.length - 1); if (prefix === '') return ''; } } return prefix; }算法步骤:
- 取第一个字符串为初始前缀
- 遍历后续字符串,用
indexOf检查前缀匹配 - 不匹配时用
substring缩短前缀 - 前缀为空时立即返回
复杂度分析:
- 时间复杂度:O(S),S为所有字符串字符总数
- 空间复杂度:O(1),只使用常数额外空间
实战技巧与性能考量
在真实面试场景中,除了写出正确解法,还需要关注代码效率。以下是几个优化方向:
1. 避免不必要的字符串操作
// 不推荐:频繁创建新字符串 let result = ''; for (const char of str) { result += char; // 每次拼接都创建新字符串 } // 推荐:使用数组暂存 const arr = []; for (const char of str) { arr.push(char); } return arr.join('');2. 善用API的特性差异
| 方法 | 负参数处理 | 性能 | 适用场景 |
|---|---|---|---|
| slice | 支持 | 一般 | 需要负索引时 |
| substring | 自动调整 | 较快 | 精确位置切割 |
| substr | 已废弃 | 慢 | 不推荐使用 |
3. 正则表达式的预编译
// 高频使用时预编译正则 const templateRegex = /\{(\w+)\}/g; function render(template: string) { return template.replace(templateRegex, ...); }在最近的TypeScript 5.0中,字符串处理性能有显著提升。特别是在大型字符串操作时,引擎优化使得slice和substring的差异变得更小,但算法题中通常字符串长度有限,选择最语义化的API更重要。