题目
在一个给定的字符串str中(如1232jdfld12388dd1290ssd),查找子串childStr(如12),返回任一子串的下标(0或者9或者16)。
要求
- 返回的下标(0|9|16)机会是均等的
- 不能开任何空间存储下标(空间复杂的O1)
- 只能遍历一次
先看一下子串的索引位置
const str = '1232jdfld12388dd1290ssd';
const childStr = '12';
const strLen = str.length;
const childStrLen = childStr.length;
const count = strLen - childStrLen;
const indexes = [];
for (let i = 0; i <= count; i++) {
if (childStr === str.slice(i, i + childStrLen)) {
indexes.push(i);
}
}
思路
- 因为不能开辟额外存储空间,我们不能使用上面查找出所有索引的方式。
- 换个思路我们可以从任意一个位置开始查找。
实现(初版)
function oneIndexOfChild(str, childStr) {
const strLen = str.length;
const childStrLen = childStr.length;
const count = strLen - childStrLen + 1;
let from = Math.floor(Math.random() * count);
let index;
do {
index = str.indexOf(childStr, from);
from--;
} while (index === -1 && from >= 0);
return index;
}
问题
如果子串分布在一头(如1123456789),当搜索子串1时,极大概率返回的是靠右的1。
改进一
function oneIndexOfChild(str, childStr) {
const strLen = str.length;
const childStrLen = childStr.length;
const count = strLen - childStrLen + 1;
let from = Math.floor(Math.random() * count);
let index;
do {
index = str.indexOf(childStr, from);
if (from === 0) break;
from = Math.floor(Math.random() * from);
} while (index === -1 && from >= 0);
return index;
}
测试结果
目前解决的是靠左的问题。
TODO
目前还没真正解决机会均等的问题。