patternjavaModerate
Palindrome tester
Viewed 0 times
palindrometesterstackoverflow
Problem
This program takes lines of input. The first line is an
I know this can be substantially improved, but I don't know how. Could I somehow capitalize on the fact that only characters a-z are used?
int specifying how many further lines will be input. For the following lines (comprised of characters a-z), it will be determined whether removing one character from the line can result in the line being a palindrome.I know this can be substantially improved, but I don't know how. Could I somehow capitalize on the fact that only characters a-z are used?
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
int cases = Integer.parseInt(br.readLine());
for (int i = 0; i < cases; i++) {
System.out.println(canBePalindrome(br.readLine()) ? "YES" : "NO");
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static boolean canBePalindrome(String line) {
if (line.length() <= 1) {
return false;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < line.length(); i++) {
if (isPalindrome(sb.append(line).deleteCharAt(i).toString())) {
return true;
}
sb.setLength(0);
}
return false;
}
private static boolean isPalindrome(String line) {
return line.equals(new StringBuilder(line).reverse().toString());
}
}Solution
main()Your main function looks good, except for the catch-all exception handler. It leaves me wondering what sorts of exceptions might be lurking in the code. I believe you are mainly concerned with
IOException, so just catch those. Better yet, just declare main(String[] args) throws IOException, as the built-in behaviour is to print a stack trace and abort.The class could be better named. I suggest
PalindromeChecker instead of Main.isPalindrome()That is a straightforward "brute-force" implementation — a direct translation of the task into code. It has some virtues, but performance is not one of them.
Here is an algorithm that could work faster, since it involves no new objects:
public static boolean isPalindrome(String s) {
for (int i = 0, j = s.length() - 1; i < j; i++, j--) {
if (s.charAt(i) != s.charAt(j)) {
return false;
}
}
return true;
}canBePalindrome()The method name leaves me puzzled as to how it differs from
isPalindrome(). I suggest renaming it to isAlmostPalindrome().You could implement it using a variant of the algorithm above.
public static boolean isAlmostPalindrome(String s) {
int i, j;
int fuzz = 0;
for (i = 0, j = s.length() - 1; i < j; i++, j--) {
if (s.charAt(i) != s.charAt(j)) {
if (++fuzz < 1) {
j++; // Pretend to delete charAt(i)
} else {
break;
}
}
}
if (fuzz == 1 || (i == j && fuzz == 0)) {
return true;
}
// The code below is identical to the code above except for the one commented line
fuzz = 0;
for (i = 0, j = s.length() - 1; i < j; i++, j--) {
if (s.charAt(i) != s.charAt(j)) {
if (++fuzz < 1) {
i--; // Pretend to delete charAt(j)
} else {
break;
}
}
}
return false;
}But wait… repeating code like that is kind of nasty. We can do better, I think.
private static boolean isPalindrome(String s, int firstIndex, int lastIndex) {
for (int i = firstIndex, j = lastIndex; i < j; i++, j--) {
if (s.charAt(i) != s.charAt(j)) {
return false;
}
}
return true;
}
public static boolean isPalindrome(String s) {
return isPalindrome(s, 0, s.length() - 1);
}
public static boolean isAlmostPalindrome(String s) {
for (int i = 0, j = s.length() - 1; i < j; i++, j--) {
if (s.charAt(i) != s.charAt(j)) {
return isPalindrome(s, i + 1, j)
|| isPalindrome(s, i, j - 1);
}
}
// Exact palindrome. Any palindrome is also an almost-palindrome,
// by deleting one of the middle characters.
return true;
}Code Snippets
public static boolean isPalindrome(String s) {
for (int i = 0, j = s.length() - 1; i < j; i++, j--) {
if (s.charAt(i) != s.charAt(j)) {
return false;
}
}
return true;
}public static boolean isAlmostPalindrome(String s) {
int i, j;
int fuzz = 0;
for (i = 0, j = s.length() - 1; i < j; i++, j--) {
if (s.charAt(i) != s.charAt(j)) {
if (++fuzz < 1) {
j++; // Pretend to delete charAt(i)
} else {
break;
}
}
}
if (fuzz == 1 || (i == j && fuzz == 0)) {
return true;
}
// The code below is identical to the code above except for the one commented line
fuzz = 0;
for (i = 0, j = s.length() - 1; i < j; i++, j--) {
if (s.charAt(i) != s.charAt(j)) {
if (++fuzz < 1) {
i--; // Pretend to delete charAt(j)
} else {
break;
}
}
}
return false;
}private static boolean isPalindrome(String s, int firstIndex, int lastIndex) {
for (int i = firstIndex, j = lastIndex; i < j; i++, j--) {
if (s.charAt(i) != s.charAt(j)) {
return false;
}
}
return true;
}
public static boolean isPalindrome(String s) {
return isPalindrome(s, 0, s.length() - 1);
}
public static boolean isAlmostPalindrome(String s) {
for (int i = 0, j = s.length() - 1; i < j; i++, j--) {
if (s.charAt(i) != s.charAt(j)) {
return isPalindrome(s, i + 1, j)
|| isPalindrome(s, i, j - 1);
}
}
// Exact palindrome. Any palindrome is also an almost-palindrome,
// by deleting one of the middle characters.
return true;
}Context
StackExchange Code Review Q#69550, answer score: 10
Revisions (0)
No revisions yet.