在Swift中实现strStr(); 早破

访谈编码中经常使用的一个经典问题(LeetCode的问题28)是:

创建一个将两个字符串s1和s2作为参数的函数,并找到一个整数,该整数表示子字符串s2在字符串s1中第一次出现的位置。

[由于您(这样很好)问到,参数s1和s2由小写英文字母ascii [az]组成,并且s1和s2中的一个(或两者)可以是空字符串“”)

Swift是一种功能强大的语言,我们当然可以利用内置函数来快速解决这个小问题。 现在,随着时间的推移,Swift String API发生了变化(并且可能有些棘手),但这并不是人类的智慧。

一个简单的解决方案— Swift

s1.range(of:s2)

这将返回一个可选的Range ? 这是我们想要的一种,但将其下限编码为一个Int。 能够?

具有比较s1 [0]和s2 [0]的高级算法。 如果没有匹配项,我们将比较s1 [1]和s2 [0],依此类推。

匹配迭代1-与s [0]匹配

显然我们不能完全匹配,因此我们不需要检查s2的其余部分。

匹配迭代2-与s [1]匹配

s2(s2 [0])的第一个元素

因此我们可以移至s1的下一个元素

s1 [1] = s2 [0]

s2的第二个元素(s2 [1])

第二个比较也匹配!

s2的第三个元素(s2 [2])

这里我们不匹配,并且s1 [1]与s [1]不完全匹配

匹配迭代3-与s1 [2]匹配

s2(s2 [0])的第一个元素

不幸的是s1 [2]与s2 [0]不匹配

匹配迭代4-与s1 [3]匹配

s2(s2 [0])的第一个元素

我们有一场比赛!

s2的第二个元素(s2 [1])

移至s1和s2的下一个元素

s2的第三个元素(s2 [2])

在这里,我们有一场完整比赛!

要知道的事-不要走得太远

实际上,我们不需要遍历s1的每个元素,实际上只需要遍历元素s1.count — s2。 计算,因为我们显然需要将s2放入s1的剩余空间中。

因此,如果s1 =“检查”并且s2 =“ aaa”,我们只需要对照s2检查s1的前4个元素。 这是因为s1.count = 6和s2.count = 3,并且我们从s1 [0]的第一个元素移到s1.count — s2.count。

这使我们在Swift中有了代码的主循环

在Swift中创建主循环

现在,我们可以使用swift的强大功能来检查匹配项…

更好的解决方案— ArraySlice

如果在Swift中将s1和s2转换为字符数组,则可以使用整数下标它们。

我们比较s1 [i]的元素,并创建一个从i到i + s2.count -1的ArraySlice(请记住,数组的索引为零,因此我们需要在此处添加“ -1”),如果它与s1相匹配,我们完成(必须将其转换为数组以匹配)。

s2的长度不能大于s1,否则根据定义我们将不匹配!

使用ArraySlice实现strStr

另一个解决方案-两个指针

你生气吗? 您想为s2使用单独的指针,即使您知道我们需要领先于ia标准号? 您想为我使用while循环吗? 好的…我们可以为j使用第二个指针,该指针遍历s2字符串。

我们知道,如果j等于s2String的长度,我们已经完成了,记住该字符串是零索引的,所以实际上写为:

j == s2Array.count — 1

好,可以

使用两个指针实现strStr

另一个解决方案-走S2阵列

想要远离阵列切片吗? 更好的是,您可以及早休息以节省一些宝贵的时间!

实现strStr遍历第二个数组

你怎么看? 早点休息重要吗?