题目为 给定一个字符串 s 和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。
注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。
第一个思路为用一个全为0的字符串去存储每一个元素是否出现过,出现就变为1。进行判断。属于暴力算法,代码逻辑没有问题,但是超时了。代码如下
public IList<int> FindSubstring(string s, string[] words)
{
int allCount = words.Count();
List<int> res = new List<int>();
if (allCount == 0)
{
return res;
}
bool[] flagAll = new bool[allCount];
int countMax = words[0].Length;
int resFlag = 0;
int resTemp = 0;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < allCount; i++)
{
sb.Append("0");
}
string[] rs = new string[allCount];
string equalsNums = sb.ToString();
for (int i = 0; i <= s.Length - countMax * allCount; i++)
{
words.CopyTo(rs, 0);
int wStart = i;
resTemp = i;
while (rs.ToList().Contains(s.Substring(wStart, countMax)))
{
if (equalsNums[rs.ToList().IndexOf(s.Substring(wStart, countMax))] == '0')
{
var r = rs.ToList().IndexOf(s.Substring(wStart, countMax));
equalsNums = equalsNums.Remove(r, 1);
equalsNums = equalsNums.Insert(r, "1");
wStart += countMax;
resFlag++;
rs[r] = "";
if (resFlag == allCount)
{
res.Add(resTemp);
break;
}
if (wStart + countMax > s.Length)
{
break;
}
}
else
{
i += wStart;
break;
}
}
equalsNums = sb.ToString();
resFlag = 0;
continue;
}
return res;
}
第二种思路是参考精选题解的方法,一个键值对,键存储元素,值存储元素出现次数。遍历时再创建一个键值对,将两个键值对比较。如果出现次数大于基准字符串出现次数,直接跳出。代码如下
public IList<int> FindSubstring(string s, string[] words)
{
List<int> res = new List<int>();
int wordNum = words.Length;
if (wordNum == 0)
{
return res;
}
int wordLen = words[0].Length;
Dictionary<string, int> dic = new Dictionary<string, int>();
foreach (var item in words)
{
if (!dic.ContainsKey(item))
{
dic.Add(item, 1);
}
else
{
dic[item] += 1;
}
}
for (int i = 0; i < s.Length - wordNum * wordLen+1; i++)
{
Dictionary<string, int> dicDetail = new Dictionary<string, int>();
int num = 0;
while (num< wordNum)
{
string word = s.Substring(i+num* wordLen,wordLen);
if (dic.ContainsKey(word))
{
if (dicDetail.ContainsKey(word))
{
dicDetail[word] += 1;
}
else
{
dicDetail.Add(word, 1);
}
if (dicDetail[word] > dic[word])
{
break;
}
}
else
{
break;
}
num++;
}
if (num==wordNum)
{
res.Add(i);
}
}
return res;
}