【问题标题】:Replace String sequence using Recursion [closed]使用递归替换字符串序列[关闭]
【发布时间】:2013-01-22 03:07:45
【问题描述】:

Java 有 replace() 和 replaceAll() 方法可以用给定的新模式替换字符串的部分/序列。该函数的内部是如何工作的?如果我必须编写一个函数来输入字符串、OldPattern、NewPattern 并在不使用 RegEx 的情况下用 NewPattern recursively 替换所有出现的 OldPattern 怎么办? 我已经使用 String 输入的迭代完成了以下代码,它似乎可以工作。如果输入是字符数组而不是字符串怎么办?

  public String replaceOld(String aInput, String aOldPattern, String aNewPattern)
        {
             if ( aOldPattern.equals("") ) {
                throw new IllegalArgumentException("Old pattern must have content.");
             }

             final StringBuffer result = new StringBuffer();
             int startIdx = 0;
             int idxOld = 0;
             while ((idxOld = aInput.indexOf(aOldPattern, startIdx)) >= 0) {
               result.append( aInput.substring(startIdx, idxOld) );
               result.append( aNewPattern );

               //reset the startIdx to just after the current match, to see
               //if there are any further matches
               startIdx = idxOld + aOldPattern.length();
             }
             //the final chunk will go to the end of aInput
             result.append( aInput.substring(startIdx) );
             return result.toString();
          }

【问题讨论】:

  • 我不确定你在这里问什么。您似乎已经解决了您的问题,将字符数组转换为字符串是微不足道的。
  • 如果您的代码工作正常,那么您可以使用toString() 函数将输入的字符数组转换为字符串,执行上述分析,并在返回修改后的字符串时使用将其转换回字符数组toCharAprray() 函数。
  • 我正在寻找一种使用递归的方法。我仅通过使用循环/迭代方法解决了这个问题。这是一个面试问题,他们要求不使用任何替换/替换所有方法的递归解决方案。

标签: java string recursion replace


【解决方案1】:

Java 有 replace() 和 replaceAll() 方法可以用给定的新模式替换字符串的部分/序列。

确切地说,这些方法会创建替换相关字符的新字符串。 Java 字符串是不可变的。

该函数的内部是如何工作的?

这太复杂了,无法在这里详细解释。 (并且细节实际上可能因一种实现而异)。最好的办法是自己阅读相关库类的源代码。 (源代码作为 JDK 的一部分分发,您的 Java IDE 应该能够向您展示它。或者,Google 搜索会在网络上为您找到它。)

如果我必须编写一个函数来输入字符串、OldPattern、NewPattern 并在不使用 RegEx 的情况下递归地用 NewPattern 替换每个出现的 OldPattern 怎么办?

好吧,如果您在谈论不使用 Pattern 类的情况下进行模式匹配/替换,那么是的,会很棘手......更不用说它毫无意义了。

(递归解决方案可能很危险。考虑这个问题:“递归地用“a”中的“ba”替换“a”的所有实例。结果应该是什么?你甚至应该尝试这样做吗?)


假设参数是简单的字符串(不是您描述的模式),那么这是一个递归解决方案(未经测试):

public String replace1(String in, String target, String replacement) {
    if (target.isEmpty()) {
        return in;
    }
    int pos = in.indexOf(target);
    if (pos < 0) {
        return in;
    }
    String updated = in.substring(0, pos) + replacement + 
                     in.substring(pos + target.length());
    return replace1(updated, target, replacement);
}

这解决了1您希望替换为递归的问题的版本;即您要替换由替换过程插入的target 实例。如果你不想这样做,那么:

public String replace2(String in, String target, String replacement) {
    if (target.isEmpty()) {
        return in;
    }
    int pos = in.indexOf(target);
    if (pos < 0) {
        return in;
    }
    return in.substring(0, pos) + replacement + 
                     replace2(in.substring(pos + target.length()),
                             target, replacement);
}

请注意,这些方法的效率很可能低于您的原始迭代解决方案。甚至忽略正在进行的所有字符串复制。 Java 不做尾调用优化。


1 - 如果您使用病态参数调用replace1,您将得到堆栈溢出。例如replace1("ab", "b", "b")

【讨论】:

  • 感谢您的回答。这确实是一个非常有趣的观点,但面试的问题要求您递归地进行而不使用替换或模式匹配。假设您被允许进行模式匹配,那么您将如何进行递归呢?您可以匹配和替换任意数量的字符。
  • 如果面试官要求你递归解决问题,那么他可能是一个糟糕的面试官。如果这反映了整个公司,你可能不想为他们工作。但如果你真的、真的需要这份工作,你可能需要花几个小时来解决这个问题……因为至少需要这个时间才能得到一个最小的解决方案。
【解决方案2】:

试试

public static String replaceOld(String aInput, String aOldPattern, String aNewPattern, int i) {
    i = aInput.indexOf(aOldPattern, i);
    if (i == -1) {
        return aInput;
    }
    aInput = aInput.substring(0, i) + aNewPattern + aInput.substring(i + aOldPattern.length());
    return replaceOld(aInput, aOldPattern, aNewPattern, i + aNewPattern.length());
}

注意参数i是用来优化的,所以indexOf不会每次都从pos 0开始扫描。并且它还解决了“a”问题中“递归地用“ba”替换所有“a”实例。

【讨论】:

  • 感谢您的回答。您的递归解决方案非常完美!
  • 但不幸的是它使用了替换方法。我正在寻找使用递归的纯算法解决方案。
  • 如果你被允许使用子字符串,那么试试我的更新
【解决方案3】:

也许这种方法会回答你的问题。

  static int indexOf(char[] string, char[] pattern, int startIndex) {
     int index = startIndex;
     while(true) {
         while(index < string.length && string[index] != pattern[0]) index++;
         if(index >= string.length || index+pattern.length > string.length) return -1;
         boolean match = true;
         for(int i = 1; i < pattern.length; i++) {
             if(string[index+i] != pattern[i]) {
                 match = false;
                 break;
             }
         }
         if(match) return index;
         else index += 1;
     }
  }

如果你想要一个递归替换方法,使用这个

static String replace(String string, String pattern, String replacement) {
  int index = string.indexOf(pattern);
  if(index < 0) return string;
  int endIndex = index+pattern.length();
  return string.substring(0, index) + replacement +
      replace(string.substring(endIndex), pattern, replacement);
}

【讨论】:

  • 感谢您的回答。除了布尔检查之外,您的解决方案再次与我所做的非常相似。我一直在寻找一种递归解决方案,这种解决方案在面试中(比如)更快且令人印象深刻。
猜你喜欢
  • 1970-01-01
  • 2011-05-09
  • 2011-09-27
  • 2016-04-30
  • 1970-01-01
  • 1970-01-01
  • 2017-04-24
  • 2021-08-21
  • 2012-11-12
相关资源
最近更新 更多