算法:随机返回字符串中的子串的任一索引

171 阅读1分钟

题目

在一个给定的字符串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);
  }
}

image.png

思路

  1. 因为不能开辟额外存储空间,我们不能使用上面查找出所有索引的方式。
  2. 换个思路我们可以从任意一个位置开始查找。

实现(初版)

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;  
}

image.png

问题

如果子串分布在一头(如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;  
}

测试结果

image.png

目前解决的是靠左的问题。

TODO

目前还没真正解决机会均等的问题。