[英]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 的解决方案。
它在开头和结尾的字符之间查找第一个不匹配的索引,并生成从最开始的0
到mismatch
索引的子字符串。
如果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
个字符匹配, i
从length() / 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
这是测试代码的链接:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.