【问题标题】:CodingBat starOut, why using substring won't work correctlyCodingBat starOut,为什么使用子字符串不能正常工作
【发布时间】:2023-04-09 20:21:01
【问题描述】:

我正在解决 CodingBat.com 上的编码挑战。问题来了:

给定一个字符串和一个非空字符串,返回一个版本 所有字符都被加号(“+”)替换的原始字符串, 除了保留的单词字符串的外观 不变。

plusOut("12xy34", "xy") → "++xy++" 
plusOut("12xy34", "1") → "1+++++"
plusOut("12xy34xyabcxy", "xy") → "++xy++xy+++xy"

这是我尝试的解决方案:

public String plusOut(String str, String word)
{
  String ret = "";
  for (int i = 0; i < str.length() - word.length() + 1; ++i) {
    if (str.substring(i, i + word.length()).equals(word))
      ret += word;
    else
      ret += "+";
  }
  return ret;
}

但是给出了错误的输出:给出了太多的加号。我不明白为什么这不应该工作。我怀疑 substring 方法没有返回足够的匹配项,所以附加了加号。但我不明白为什么会这样。

【问题讨论】:

  • 你试过调试你的代码吗?

标签: java string substring


【解决方案1】:

我会使用 StringBuilder 来构造结果以避免创建多个 String 对象,因为 Java 中的 String 是不可变的:

public String plusOut(String str, String word) {
  StringBuilder result = new StringBuilder(str);
  int len = str.length(), wordLen = word.length(), index = 0;
  while(index < len){
    if ( (index <= len-wordLen) && (str.substring(index, index+wordLen).equals(word))){
      index += wordLen;
      continue;
    }
    result.setCharAt(index++, '+');
  }
  return result.toString();
}

【讨论】:

  • 迄今为止我见过的最明智的解决方案。很高兴解释为什么作者当前的实现不起作用。
【解决方案2】:

你做错了一些事情。我已经更正了您的代码,尽管可能有更简洁的方法可以做到这一点。我将在下面解释发生了什么变化。

public static String plusOut(String str, String word)
{
    String ret = "";
    for (int i = 0; i < str.length(); ++i) {
        int endIndex = i + word.length();
        if (endIndex < str.length() + 1
                && str.substring(i, i + word.length()).equals(word)) {
            ret += word;
            i = i + word.length() - 1;
        } else
            ret += "+";
    }
    return ret;
}

第一个错误是您没有循环遍历str 的全部内容,因此永远不会到达str 的最后一个字符。

另一个问题是,一旦你找到一个单词,你并没有在循环中“跳转”到正确的 next 索引,而是继续循环遍历找到的单词的字符,这会导致结果字符串中有额外的+ 字符。

i = i + word.length() - 1;

在您的解决方案中,上述内容会将您带到您应该查看的 str 中字符的下一个索引。示例:

在字符串12xy34xyabcxy 中寻找xy

您会发现单词xy 开始于索引2 并结束于3。 此时,在将找到的word 添加到其中后,您将获得结果字符串++xy

现在,问题开始了。您仍然最终会遍历索引 3 并添加一个额外的 +,因为接下来的几个字符不符合您的单词。

找到xy后的2个字符也加上+,你现在有++xy+++这是不正确的。

endIndex < str.length() + 1

endIndex 以它的名字命名 - 你的子字符串的结束索引。

当从当前索引到最后一个字符串中没有足够的字符以弥补xy时,此检查阻止我们检查xy,因此我们最终为剩余的每个添加+字符。

【讨论】:

    【解决方案3】:

    这样做:

    public static String plusOut(String str, String word)
    {
        String ret = "";
        int i;
        for (i = 0; i < str.length() - word.length() +1 ; i++) {
            if (str.substring(i, i + word.length()).equals(word)) {
                ret += word;
                i += word.length() - 1;
            }
            else
                ret += "+";
        }
        while (i < str.length()) {
            ret += "+";
            i++;
        }
    
        return ret;
    }
    

    【讨论】:

    • 检查你的时间复杂度——你循环了两次。
    • 不只是其余长度的两倍,兄弟。 @curiousdev
    • 糟糕,我错过了您在循环上方声明 i 的事实
    【解决方案4】:

    这是你的解决方案

        public String plusOut(String str, String word)
    {
        String ret = "";
        for (int i = 0; i < str.length();) {
            if (i + word.length()<= str.length() && str.substring(i, i + word.length()).equals(word)) {
                ret += word;
                i+=word.length();
            }
            else{
                ret += "+";
                i++;
            }
        }
        return ret;
    }
    

    【讨论】:

      猜你喜欢
      • 2021-10-15
      • 1970-01-01
      • 1970-01-01
      • 2012-01-27
      • 2014-01-06
      • 2016-07-14
      • 2016-07-16
      • 2019-01-04
      • 2020-09-03
      相关资源
      最近更新 更多