我试图在java中解决这个问题。我有一个回文字符串的arraylist。我必须从给定的数组列表中找到最短的回文串。我已经解决了这个问题,但我正在寻求获得有关我的代码的反馈,以及我如何尝试使代码更有效/更好。
以下是我尝试的代码。
在这种情况下,大小将为3,因为这是最小的回文字符串的长度。
import java.util.ArrayList;
class ShortestPalindrome {
public static int isShortestPalindrome(ArrayList<String> list) {
int smallest = list.get(0).length();
boolean ret = false;
for (String element : list) {
ret = isPalindrome(element);
if (ret) {
if (element.length() < smallest)
smallest = element.length();
}
}
return smallest;
}
private static boolean isPalindrome(String input) {
String str = "";
boolean result = false;
if (input.length() == 1 || input.length() == 0)
return true;
if (input.charAt(0) != input.charAt(input.length() - 1))
return false;
StringBuilder sb = new StringBuilder(input.toLowerCase());
str = sb.reverse().toString();
if (input.equals(str)) {
result = true;
}
return result;
}
public static void main(String[] args) {
ArrayList<String> array = new ArrayList<String>();
array.add("malayam");
array.add("aba");
array.add("abcdeyugugi");
array.add("nitin");
int size = isShortestPalindrome(array);
System.out.println("Shortest length of string in list:" + size);
}
}
答案 0 :(得分:1)
对代码的最简单改进是,只检查字符串是否是回文,如果它的长度小于smallest
。
Btw初始化int smallest = list.get(0).length();
不正确,想象第一个元素不是回文并且是所有字符串的最小尺寸。你应该int smallest = Integer.MAX_VALUE;
还检查
if (input.charAt(0) != input.charAt(input.length() - 1))
return false;
不正确,因为您不会将字符转换为小写字母(如稍后所做),因此"ajA"
不会是回文。
您的代码可能会有进一步的改进:
您可以通过复制和倒车替换回文检查:
for (int i = 0; i < input.length() / 2; ++i)
if (Character.toLowerCase(input.charAt(i)) != Character.toLowerCase(input.charAt(input.length() - 1 - i)))
return false;
这里没有必要的副本,在一般情况下它可能更快(因为它可以提前终止)。
另外,就像AKSW提到的那样,按照长度对字符串进行排序可能会更快,然后一旦找到回文就可以提前终止。
答案 1 :(得分:1)
我对您的代码有几点意见:
isPalindrome()
。isPalindrome()
方法:
n
的字符串需要 n 时间和其他 n 空间。比较两者也需要 n 时间。显然,当使用限制进行复杂度计算时,时间复杂度是相同的 - O(n) - 但第二种解决方案仍然便宜4倍,并且花费的空间可以忽略不计。
因此,我相信这是实现测试的最有效方式:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
class ShortestPalindrome {
public static int isShortestPalindrome(ArrayList<String> list) {
// Sorts the given ArrayList by length
Collections.sort(list, Comparator.comparingInt(String::length));
for (String element : list) {
if(isPalindrome(element)) {
return element.length();
}
}
return -1; // If there is no palindrome in the given array
}
private static boolean isPalindrome(String input) {
String lowerCased = input.toLowerCase();
int pre = 0;
int end = lowerCased.length() - 1;
while (end > pre) {
if (lowerCased.charAt(pre) != lowerCased.charAt(end))
return false;
pre ++;
end --;
}
return true;
}
public static void main(String[] args) {
ArrayList<String> array = new ArrayList<>(Arrays.asList("malayam", "aba", "abcdeyugugi", "nitin"));
int size = isShortestPalindrome(array);
System.out.println("Shortest length of string in list: " + size);
}
}
编辑:我已使用以下列表测试了此算法。在检查回文之前对列表进行排序可以减少50%的运行时间。
&#34; malayam&#34;,&#34; aba&#34;,&#34; abcdeyugugi&#34;,&#34; nitin&#34;,&#34; sadjsaudifjksdfjds&#34;,&# 34; sadjsaudifjksdfjdssadjsaudifjksdfjds&#34;,&#34; sadjsaudifjksdfjdssadjsaudifjksdfjdssadjsaudifjksdfjds&#34;,&#34; a&#34;
答案 2 :(得分:0)
下面简单的代码应该适合你。 首先检查长度然后检查它实际上是否是回文。 如果是,那么只需将其存储在最小的
中public static int isShortestPalindrome(ArrayList<String> list) {
Integer smallest = null;
for(String s:list){
if ( (smallest == null || s.length()< smallest) && new StringBuilder(s).reverse().toString().equalsIgnoreCase(s) ){
smallest = s.length();
}
}
return smallest == null ? 0 :smallest;
}
答案 3 :(得分:0)
这是一个流版本:
OptionalInt minimalLenOfPalindrome
= list.paralellStream()
.filter(st -> {
StringBuilder sb = new StringBuilder(st);
String reversedSt = sb.reverse().toString();
return st.equalsIgnoreCase(reversedSt);
})
.mapToInt(String::length)
.min();
感谢@yassin回答我正在使用以下代码更改代码:
public class SOFlow {
private static boolean isPalindrome(String input) {
for (int i = 0; i < input.length() / 2; ++i) {
if (Character.toLowerCase(input.charAt(i)) != Character.toLowerCase(input.charAt(input.length() - 1 - i))) {
return false;
}
}
return true;
}
public static void main(String args[]) {
List<String> list = new ArrayList<>();
list.add("cAcc");
list.add("a;;;;a");
list.add("aJA");
list.add("vrrtrrr");
list.add("cAccccccccc");
OptionalInt minimalLenOfPalindrome
= list.parallelStream()
.filter(SOFlow::isPalindrome)
.mapToInt(String::length)
.min();
System.out.println(minimalLenOfPalindrome);
}
}
答案 4 :(得分:0)
使用Java8流,并首先考虑排序,原因与其他原因相同:
boolean isPalindrome (String input) {
StringBuilder sb = new StringBuilder(input.toLowerCase());
return sb == sb.reverse();
}
public static int isShortestPalindrome(ArrayList<String> list) {
return (list.stream().sorted ((s1, s2) -> {
return s1.length () - s2.length ();
})
.filter (s-> isPalindrome (s))
.findFirst ()
.map (s -> s.length ())
.orElse (-1));
}
如果你有很多相等,最小长度,非常长的弦乐,只有非中间的非回文,你可能会花费很多时间在isPalindrome上,喜欢isPalindrome1而不是isPalindrome。
如果我们假设一个长度均匀分布在1000到2000个字符之间的百万字符串,我们最终会集中注意力。 1000弦。如果它们中的大多数是相等的,除了几个字符,接近中间,那么微调这种比较可能是相关的。但是早期找到回文终止了我们的搜索,所以回文百分比对性能的影响也很大。
private static boolean isPalindrome1 (String s) {
String input = s.toLowerCase ();
int len = input.length ();
for (int i = 0, j = len -1; i < len/2 && j > len/2; ++i, --j)
if (input.charAt(i) != input.charAt (j))
return false;
return true;
}
流排序和过滤的结果是一个选项,这是发出信号的好机会,没有找到任何内容。我坚持你的返回int的接口,如果没有找到,则返回-1,当然,调用者必须正确评估。