可能的回文检查从给定的字符串 - 高效的代码需要
我正在解决Palindrome index问题。问题的难度很容易,但我仍然没有通过所有的测试用例:(在大多数测试用例中,我得到了超时并且令人惊讶地发现一个测试用例也失败了。我搜索了回文检查 - 似乎只有两种方法 -可能的回文检查从给定的字符串 - 高效的代码需要
。1. Using StringBuilder reverse() method.
2. Comparing characters till mid of the string length.
我尝试这两种方法,仍然没有成功
以下是我的尝试:
import java.util.Scanner;
public class PalindromeIndex {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int totalTestCases = Integer.parseInt(scanner.nextLine());
String testString = null;
StringBuffer outputString = new StringBuffer();
for (int i = 0; i < totalTestCases; i++) {
testString = scanner.nextLine();
boolean is0thElementTrue = false;
// One lettered word is always a palindrome so checked that
// condition
if (isPalindrome(testString) || testString.length() == 1) {
outputString.append("-1");
} else {
if (isPalindrome(testString.substring(1))) {
outputString.append("0 ");
is0thElementTrue = true;
}
// See here j - index starts from 1 as initial case is
// already
// handled in above if-condition
// Also see the condition checks [j < testString.length() -
// 1;]
// because (testString.length() - 1) is checked separately
// after
// this for loop.;
boolean isLoopSuccessAtleastOnce = false;
for (int j = 1; j < testString.length() - 1; j++) {
if (isPalindrome(testString.substring(0, j)
+ testString.substring(j + 1, testString.length()))) {
isLoopSuccessAtleastOnce = true;
if (is0thElementTrue) {
outputString.append(j);
is0thElementTrue = false;
} else
outputString.append(" " + j);
}
}
if (isPalindrome(testString.substring(0,
testString.length() - 1))) {
if (isLoopSuccessAtleastOnce)
outputString.append(" " + (testString.length() - 1));
else
outputString.append((testString.length() - 1));
}
}
outputString.append("\n");
}
System.out.println(outputString.toString());
scanner.close();
}
private static boolean isPalindrome(String str) {
StringBuilder strBuffer = new StringBuilder(str);
return str.equalsIgnoreCase(strBuffer.reverse().toString());
}
private static boolean isPalindrome_2ndWay(String str) {
int n = str.length();
for (int i = 0; i < (n/2) + 1; ++i) {
if (str.charAt(i) != str.charAt(n - i - 1)) {
return false;
}
}
return true;
}
}
您的解决方案是二次的,这绝对不是该网站所寻找的,您可以做得更好。
请考虑这一点。如果第一个和最后一个字符不相等,那么其中一个就是答案。如果它们相同,则可以将相同的逻辑应用于第二个和最后一个字符之前的逻辑。等
这将是我的答案:
String text = "Anita lava la tina";
text = text.toLowerCase().replaceAll(" ", "");
StringBuilder strb = new StringBuilder(text);
String text2 = strb.reverse().toString();
System.out.println("Palindrome: " + text.equals(text2));
尝试更有效的解决方案:使用StringBuilder.deleteCharAt(int index)
但要注意,您必须将其放回或从要创建的字符串中新建StringBuilder
以进行测试。然后你可以遍历字符,删除它们并使用你现有的方法测试结果字符串。
小记:
注:如果给定索引处的字符是增补字符,这种方法并不能删除整个字符。
...但我不认为这是测试你的Unicode知识在这一点上。
的问题表述为
弄清楚其上去除将使串回文字符的索引。总会有一个有效的解决方案。如果字符串已回文,然后-1也是一个有效的答案
因此,它可以如下走近:
- 找到的第一个字符,使字符串不是回文,换句话说,第一个字符与“镜像”位置上的字符不同。
- 如果没有这样的字符,字符串已经是回文。
- 如果有这样的字符,找出是否删除它使字符串回文。如果是这样,你已经找到了解决方案。如果没有,那么镜子位置上的角色必须是答案(问题指出总是有一个有效的解决方案)。
查找使字符串不是回文的第一个字符是O(n)。该操作每个字符串最多执行两次,所以全局解决方案仍然是O(n)。
这是一个可能的实现。它已通过所有测试
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class PalindromeIndex {
public static void main(String[] args) {
List<String> inputStrs = readInput();
for (String inputStr : inputStrs) {
int index = findIndexToRemove(inputStr);
System.out.println(index);
}
}
private static List<String> readInput() {
int inputSize;
List<String> inputStrs = new ArrayList<>();
try(Scanner scanner = new Scanner(System.in)){
inputSize = Integer.parseInt(scanner.nextLine());
for (int i = 0; i < inputSize; i++) {
inputStrs.add(scanner.nextLine());
}
}
return inputStrs;
}
private static int findIndexToRemove(String inputStr){
int i = findIndexOfDifference(inputStr);
int result;
if(i == -1){
// String is a palindrome
result = -1;
} else {
// Either the char at i or the char at the opposite side (length-1-i)
// is the char to remove. Let's remove one of them and see
// if the result is a palindrome
if(findIndexOfDifference(removeChar(inputStr, i)) == -1){
result = i;
} else {
result = inputStr.length() - 1 - i;
}
}
return result;
}
/**
* Returns the position of the first character that is not equal to the
* character at its simmetric position (i.e. the char at the same position
* counting from the opposite side of the string).
*/
private static int findIndexOfDifference(String inputStr){
int i=0, j=inputStr.length()-1;
while(i<j && inputStr.charAt(i) == inputStr.charAt(j)){
i++;
j--;
}
int index;
if(i<j){
index = i;
} else {
index = -1;
}
return index;
}
private static String removeChar(String str, int charIndex){
String firstPart = str.substring(0, charIndex);
String secondPart = str.substring(Math.min(str.length(), charIndex+1), str.length());
return firstPart + secondPart;
}
}
对于这些类型的东西,我们通常不提供实现;发布解决方案没有意义... –
@ MaartenBodewes-owlstead我可以看到你的观点......它有点挫败了谜题的全部目的,这就是要自己解决这个问题,对不起,但是,这是一个问答网站,毕竟, OP甚至没有提出任何问题,他只是表示他正在努力解决问题,迄今为止一直没有成功。所以我不认为具有完整解决方案的答案不如仅提供提示的答案有效。 – abl
我不是downvoting或任何东西,这只是未来的问题暗示。你的回答当然是结构良好的++(尽管你可以把它与我的答案结合起来,但在我看来,字面上删除一个字符更加清晰)。 –
为什么stringBuffer不是StringBuilder?为什么ignorecase等于?为什么要循环直到testString.length() - 1而不是testString.length()/ 2? – SMA
显示哪些回文失败!请始终在stackoverflow中包含错误条件。此外,似乎你有大量的代码只是从输入中获取候选,输入是如何呈现的? –
您的“第二种方式”代码不区分大小写。在进行任何测试之前,您可以考虑首先转换为全部小写或大写。那样做也会使测试速度更快(尽管这一点无关紧要)。至于你的for循环,不要使用'++ i'而不是'i ++'并且使用'i