字符串查找
实现在字符串中查找子串位置的功能,类似于 String.prototype.indexOf 方法
问题
实现一个函数,在给定的字符串中查找子串第一次出现的位置。如果找到则返回子串开始的索引位置,如果未找到则返回 -1。这是对原生 indexOf 方法的手动实现,帮助理解字符串匹配的基本原理。
解答
/**
* 在字符串中查找子串的位置
* @param {string} str - 主字符串
* @param {string} target - 要查找的子串
* @param {number} fromIndex - 开始查找的位置,默认为 0
* @returns {number} 子串首次出现的索引,未找到返回 -1
*/
function strIndexOf(str, target, fromIndex = 0) {
// 参数校验
if (typeof str !== 'string' || typeof target !== 'string') {
return -1;
}
// 空字符串特殊处理
if (target === '') {
return fromIndex >= 0 && fromIndex <= str.length ? fromIndex : 0;
}
// 处理起始位置
const startIndex = fromIndex < 0 ? 0 : fromIndex;
// 如果子串长度大于剩余字符串长度,直接返回 -1
if (target.length > str.length - startIndex) {
return -1;
}
// 遍历主字符串,查找匹配位置
for (let i = startIndex; i <= str.length - target.length; i++) {
let match = true;
// 逐字符比较
for (let j = 0; j < target.length; j++) {
if (str[i + j] !== target[j]) {
match = false;
break;
}
}
// 找到匹配,返回索引
if (match) {
return i;
}
}
// 未找到匹配
return -1;
}
// 方法二:使用 substring 进行比较(更简洁)
function strIndexOf2(str, target, fromIndex = 0) {
if (typeof str !== 'string' || typeof target !== 'string') {
return -1;
}
if (target === '') {
return fromIndex >= 0 && fromIndex <= str.length ? fromIndex : 0;
}
const startIndex = fromIndex < 0 ? 0 : fromIndex;
for (let i = startIndex; i <= str.length - target.length; i++) {
if (str.substring(i, i + target.length) === target) {
return i;
}
}
return -1;
}
使用示例
// 基本使用
console.log(strIndexOf('hello world', 'world')); // 6
console.log(strIndexOf('hello world', 'o')); // 4
console.log(strIndexOf('hello world', 'xyz')); // -1
// 指定起始位置
console.log(strIndexOf('hello world', 'o', 5)); // 7
console.log(strIndexOf('hello world', 'o', 8)); // -1
// 空字符串情况
console.log(strIndexOf('hello', '')); // 0
console.log(strIndexOf('hello', '', 3)); // 3
// 边界情况
console.log(strIndexOf('abc', 'abcd')); // -1
console.log(strIndexOf('', 'a')); // -1
console.log(strIndexOf('aaa', 'aa')); // 0
// 与原生方法对比
const str = 'JavaScript is awesome';
const target = 'is';
console.log(strIndexOf(str, target) === str.indexOf(target)); // true
关键点
- 双层循环匹配:外层循环遍历主字符串的每个可能起始位置,内层循环逐字符比较子串
- 边界条件处理:
- 空字符串的特殊处理(返回起始位置)
- 子串长度大于剩余字符串时直接返回 -1
- 起始位置的合法性校验
- 优化搜索范围:外层循环只需遍历到
str.length - target.length,避免无效比较 - 提前终止:内层循环发现不匹配时立即 break,提高效率
- 时间复杂度:O(n * m),其中 n 是主字符串长度,m 是子串长度
- 可选优化:可以使用 KMP、Boyer-Moore 等高级算法将时间复杂度优化到 O(n + m)
目录