繁体   English   中英

Codingbat 挑战:mirrorEnds 使用 Stream API

[英]Codingbat challenge: mirrorEnds using Stream API

给定来自CodingBat 的任务 mirrorEnds

给定一个字符串,在给定字符串的开头和结尾查找镜像(向后)字符串。

换句话说,在给定字符串的开头有零个或多个字符,并且在字符串的最后以相反的顺序(可能重叠)。 例如,字符串"abXYZba"具有镜像端"ab"

例子:

mirrorEnds("abXYZba")  →  "ab"
mirrorEnds("abca")     →  "a"
mirrorEnds("aba")      →  "aba"

我对此任务的解决方案如下:

public String mirrorEnds(String str) {
  String result = "";
  
  if (str.length() % 2 != 0) {
    for (int i = 0; i < str.length() / 2; i++) {
      if (str.charAt(i) == str.charAt(str.length() - i - 1)) {
        result += "" + str.charAt(i);
      } else {
        break;
      }
    }
    
    if (result.length() == str.length() / 2) {
      String strEnd = new StringBuilder(result).reverse().toString();
      result += "" + str.charAt(str.length() / 2) + strEnd;
    } 
  }
  
  if (str.length() % 2 == 0) {
    for (int i = 0; i < str.length() / 2; i++) {
      if (str.charAt(i) == str.charAt(str.length() - i - 1)) {
        result += "" + str.charAt(i);
      } else {
        break;
      }
    }
    
    if (result.length() == str.length() / 2) {
      String strEnd = new StringBuilder(result).reverse().toString();
      result += strEnd;
    }
  }
  
  return result;
}

是否可以使用Stream API解决这个问题?

我认为 Stream API 不会给你任何优势。 但是,您可以像这样优化您的代码

  public String mirrorEnds(String string) {
    StringBuilder result = new StringBuilder();

    for (int i = 0; i < string.length(); i++) {
        if (string.charAt(i) == string.charAt(string.length() - i - 1)) {
            result.append(string.charAt(i));
        } else {
            break;
        }
    }
    return result.toString();
}

单个流语句中使用IntStream.range()是可行的。

为了创建单线,我们需要takeWhile()的帮助,它是在 Java 9 中引入的takeWhile()是一个所谓的短循环操作,即它会在第一个元素之后中断'不匹配给定的谓词

public static String mirrorEnds(String str) {
    
    return IntStream.range(0, str.length())
        .takeWhile(i -> str.charAt(i) == str.charAt(str.length() - 1 - i))
        .map(str::codePointAt)
        .collect(StringBuilder::new,
            StringBuilder::appendCodePoint,
            StringBuilder::append)
        .toString();
}

由于CodingBat仍在 Java 8 上,它的编译器会在上面的代码中报错。


@Holger提出的一个非常好的、简单的符合 Java 8 的解决方案。

它在开头和结尾的字符之间查找第一个不匹配的索引,并生成从最开始的0mismatch索引的子字符串。

如果findFirst()返回一个空的可选项,即给定字符串是回文并且没有不匹配,则给定字符串的长度将通过orElse()提供。

下面的代码通过了CodingBat上的所有测试。

public String mirrorEnds(String str) {
        
        int mismatch = IntStream.range(0, str.length() / 2)
            .filter(i -> str.charAt(i) != str.charAt(str.length() - 1 - i))
            .findFirst()
            .orElse(str.length());
        
        return str.substring(0, mismatch);
    }

请注意,由于CodingBat不允许导入,因此为了在此站点上运行上述代码,您需要使用java.util.stream.IntStream类的所谓完全限定名称。

由于您故意要求解决此问题的流式解决方案,因此这可能是寻找最大索引i ,其中前i个字符与倒置的最后i个字符匹配, ilength() / 2开始并递减i直到它达到 0。

仅当给定字符串不是回文时才应用前面的算法才有意义。 事实上,在这种情况下,字符串本身可以立即返回。

public static String mirrorEnds(String str) {
    if (str.equals(new StringBuilder(str).reverse().toString())) {
        return str;
    }

    OptionalInt maxLen = IntStream.iterate(str.length() / 2, i -> i >= 0, i -> i - 1)
            .filter(i -> str.substring(0, i).equals((new StringBuilder(str.substring(str.length() - i))).reverse().toString()))
            .max();

    return maxLen.isPresent() ? str.substring(0, maxLen.getAsInt()) : null;
}

输出

ab
a
aba

这是测试代码的链接:

https://www.jdoodle.com/iembed/v0/rUL

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM