【问题标题】:Leetcode 28 - Implement strStr(): questionLeetcode 28 - 实现 strStr():问题
【发布时间】: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()。另外,我没有重新格式化这个问题,所以会有冗余;我主要关心的是为什么会发生这个特定的错误。非常感谢!

标签: c++ string algorithm function strstr


【解决方案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!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-11
    • 2022-06-12
    • 1970-01-01
    • 2021-09-22
    • 2015-09-29
    相关资源
    最近更新 更多