Leetcode 28 - 实现 strStr():问题

Posted

技术标签:

【中文标题】Leetcode 28 - 实现 strStr():问题【英文标题】:Leetcode 28 - Implement strStr(): question 【发布时间】:2019-08-06 14:51:07 【问题描述】:

我在提交 Leetcode 28 时遇到了一个迄今为止我一直没有发现的错误。我的代码适用于大多数测试用例,但我对诸如 haystack = "mississippi", needle = "issip" 等场景感到困惑。

我尝试过调试,发现整个 haystack 字符串都被迭代了,它返回 -1 或未找到。它在每次出现“i”时找到的子字符串长度为 4、1、1。

int strStr(string haystack, string needle) 
        if (needle.empty()) 
            return 0;
        
        if (haystack.empty() && !needle.empty()) 
            return -1;
        
        int i = 0, j = 0, ans = 0;
        for (i; i < haystack.length(); i++) 
            if (haystack[i] == needle[0]) 
                j = 0;
                ans = i;
                for (j; j < needle.length(); j++) 
                    /*
                    if (haystack[i++] == needle[j]) 
                        continue;
                    
                    else 
                        break;
                    
                    */
                    if (haystack[i++] != needle[j]) 
                        break;
                    
                
                if (j == needle.length()) 
                    return ans;
                
            
            if (j == needle.length()) 
            return ans;
            
        
        return -1;
    

输入:“mississippi”、“issip” 输出:-1(ans = 10,j = 1)

【问题讨论】:

与您的问题无关,但您的第二个 if 无缘无故地过于复杂。如果needle不为空,则无需再次检查。 也许您应该解释一下,为什么haystack.find(needle) 不是您问题的答案?您可能有人为的限制,但请列出它们。 你看到haystack[i++] 的副作用了吗?您是否看到它如何跳过您的for (i;... 循环中的扫描规律?您对“整个 haystack 字符串进行迭代”的断言是错误的。 是的,限制是这样的,所以我想主要手动编写解决方案,除了非常简单的方法,例如 empty() 和 length()。另外,我没有重新格式化这个问题,所以会有冗余;我主要关心的是为什么会发生这个特定的错误。非常感谢! 【参考方案1】:

这个函数有几个缺点。

对于初学者来说,它应该被声明为

std::string::size_type strStr( const std::string &haystack, const std::string &needle );

如果在第一个字符串中没有找到第二个字符串,函数应该返回std::string::npos,就像类 std::string 的所有类似成员函数一样。

函数参数shell是常量引用类型。

if 语句中的条件

if (haystack.empty() && !needle.empty())

有一个冗余操作数。它可以重写为

if (haystack.empty())

这个循环

for (i; i < haystack.length(); i++) 

当第一个字符串尾部的大小小于第二个字符串的大小时,应该停止它的迭代。

在这个 if 语句中

if (haystack[i++] != needle[j]) 

变量 i 递增,导致变量递增两次:一次在此语句中,第二次在循环中。

这些语句的第二对

        if (j == needle.length()) 
        return ans;

是多余的。

这个函数可以写成如下演示程序所示。

#include <iostream>
#include <string>

std::string::size_type strStr( const std::string &haystack, const std::string &needle )

    if ( needle.empty() )
    
        return 0;
    
    else if ( haystack.empty() )
    
        return -std::string::npos;
    
    else
    
        std::string::size_type ans = std::string::npos;

        auto n1 = haystack.length();
        auto n2 = needle.length();

        for ( std::string::size_type i = 0; ans == std::string::npos && i + n2 <= n1; i++ )
        
            std::string::size_type j = 0;
            while ( j < n2 && haystack[i+j] == needle[j] ) j++;

            if ( j == n2 ) ans = i;
        

        return ans;
    


int main() 

    std::string haystack( "mississippi" );
    std::string needle( "issip" );

    std::cout << strStr( haystack, needle ) << '\n';

    return 0;

它的输出是

4

【讨论】:

【参考方案2】:

问题是你在

中修改了i
if (haystack[i++] != needle[j]) 

从而阻止探索第二个潜在匹配。试试

if (haystack[i + j] != needle[j]) 

并修复任何连锁问题。不过,我希望它能够按原样工作。

【讨论】:

啊,我明白了! i 在发生后续匹配后递增。非常感谢,这对我不会再犯同样的错误很有帮助。 现在,要记住的是,继续前进,这是您的算法。 O(n*m)(草垛和针长的乘积)。可能足以通过这个 leetcode。但是,如果您想完善它并了解更多信息,请查看 Boyer-Moore 算法,对于 O(n+m) 谢谢,我注意到这是非常低效的 (O(n*m))。我已经知道了 Knuth-Morris-Pratt,但我也会去看看 Boyer-Moore!

以上是关于Leetcode 28 - 实现 strStr():问题的主要内容,如果未能解决你的问题,请参考以下文章

Leetcode 28 - 实现 strStr():问题

LeetCode 28 实现 strStr()

leetcode 28. Implement strStr() 实现strStr()

leetcode-----28. 实现 strStr()

LeetCode#28 | Implement strStr() 实现strStr()

python刷LeetCode:28. 实现 strStr()