Go实现首个子串匹配函数时for循环提前终止导致结果错误的问题求助
我来帮你分析下问题出在哪,你的代码核心问题是循环结构写错了,导致还没处理到正确的起始位置,循环就提前跑完了,直接返回了-1。
先看你写的for循环:
for range len(haystacks) - len(needles) + 1 { // ... 匹配逻辑 }
这种写法是让循环执行固定的len(haystacks)-len(needles)+1次,但你在循环体里还会手动修改slow变量,这就把循环次数和slow的取值完全搞脱节了。比如你的测试用例里,len(haystacks)-len(needles)+1等于7,循环会执行7次,但每次匹配失败slow都会自增,等循环次数耗尽时,可能还没轮到处理slow=4这个正确位置,就直接触发了最后的return -1。
正确的暴力匹配逻辑应该是让slow从0遍历到len(haystacks)-len(needles),每个slow对应一个子串的起始位置,而不是机械地执行固定次数的循环。你现在的写法要么会跳过某些起始位置,要么会在没处理完有效位置时就提前结束循环。
另外提一句,你把haystack和needle转换成[]rune其实是多余的(测试用例都是ASCII字符,字符串索引和rune索引完全一致),还会多占内存,但这不是当前问题的根源。
给你两种修复方案,选哪个都行:
方案一:修正循环结构,手动控制slow的遍历范围
把你的for循环改成基于slow的范围循环,确保每个可能的起始位置都被处理到:
func strStr(haystack string, needle string) int { n, m := len(haystack), len(needle) if m > n { return -1 } slow := 0 fast := 0 // 让slow遍历所有合法的起始位置 for slow <= n - m { if haystack[slow+fast] == needle[fast] { fast++ } else { slow++ fast = 0 } if fast == m { return slow } } return -1 }
方案二:更清晰的暴力匹配实现(推荐)
把每个起始位置的匹配逻辑独立出来,代码可读性更高,也不容易出逻辑漏洞:
func strStr(haystack string, needle string) int { n, m := len(haystack), len(needle) if m == 0 { return 0 } if m > n { return -1 } // 遍历所有可能的起始位置 for i := 0; i <= n - m; i++ { j := 0 // 检查从i开始的子串是否完全匹配 for j < m && haystack[i+j] == needle[j] { j++ } if j == m { return i } } return -1 }
至于你debug时看到在slow=3时返回-1,本质是因为固定次数的循环在执行到第4次时,已经耗尽了有效迭代机会,还没来得及处理slow=4这个正确位置,就直接走到了函数末尾的return -1。只要把循环改成基于slow的范围遍历,就能保证不会错过正确的起始位置。
内容来源于stack exchange

