I have a class that checks whether a string is a palindrome or not. I have two questions.
1) Is this the most efficient way to check for palindrome?
2) Can this be implemented recursively?
public class Words {
public static boolean isPalindrome(String word) {
String pal = null;
word = word.replace(" ", "");
pal = new StringBuffer(word).reverse().toString();
if (word.compareTo(pal) == 0) {
return true;
} else {
return false;
}
}
}
Have a test class to test this... Doubt its needed but here it is anyways if anyone cares to try it out to be able to help me with any of the two questions above...
public class testWords {
public static void main(String[] args) {
if (Words.isPalindrome("a") == true) {
System.out.println("true");
} else {
System.out.println("false");
}
if (Words.isPalindrome("cat") == true) {
System.out.println("true");
} else {
System.out.println("false");
}
if (Words.isPalindrome("w o w") == true) {
System.out.println("true");
} else {
System.out.println("false");
}
if (Words.isPalindrome(" a ") == true) {
System.out.println("true");
} else {
System.out.println("false");
}
if (Words.isPalindrome("mom!") == true) {
System.out.println("true");
} else {
System.out.println("false");
}
}
}
thanks in advance for any help and or input :)
To implement a 'palindrome check' recursively, you must compare if the first and last characters are the same. If they are not the same the string is most certainly not a palindrome. If they are the same the string might be a palindrome, you need to compare the 2nd character with the 2nd to last character, and so on until you have strictly less then 2 characters remaining to be checked in your string.
A recursive algorithm would look like this:
public static boolean isPalindrome(String word) {
//Strip out non-alphanumeric characters from string
String cleanWord = word.replaceAll("[^a-zA-Z0-9]","");
//Check for palindrome quality recursively
return checkPalindrome(cleanWord);
}
private static boolean checkPalindrome(String word) {
if(word.length() < 2) { return true; }
char first = word.charAt(0);
char last = word.charAt(word.length()-1);
if( first != last ) { return false; }
else { return checkPalindrome(word.substring(1,word.length()-1)); }
}
Note, that my recursion method is not most efficient approach, but
simple to understand
Marimuthu Madasamy has a more efficient recursive method, but is harder to understand
Joe F has listed an equivalently efficient iterative method
which is the best approach for implementation because it cannot cause a stack overflow error
Here is another recursive solution but using array which could give you some performance advantage over string in recursive calls (avoiding substring or charAt).
private static boolean isPalindrome(final char[] chars, final int from,
final int to) {
if (from > to) return true;
return chars[from] != chars[to] ? false
: isPalindrome(chars, from + 1, to - 1);
}
public static boolean isPalindrome(final String s) {
return isPalindrome(s.toCharArray(), 0, s.length() - 1);
}
The idea is that we keep track of two positions in the array, one at the beginning and another at the end and we keep moving the positions towards the center.
When the positions overlap and pass, we are done comparing all the characters and all the characters so far have matched; the string is palindrome.
At each pass, we compare the characters and if they don't match then the string is not palindrome otherwise move the positions closer.
It's actually sufficient to only check up to the middle character to confirm that it is a palindrome, which means you can simplify it down to something like this:
// Length of my string.
int length = myString.length();
// Loop over first half of string and match with opposite character.
for (int i = 0; i <= length / 2; i++) {
// If we find one that doesn't match then return false.
if (myString.charAt(i) != myString.charAt(length - 1 - i)) return false;
}
// They all match, so we have found a palindrome!
return true;
A recursive solution is very possible but it is not going to give you any performance benefit (and probably isn't as readable).
Can this be implemented Recursively?
YES
Here is example:
public static boolean palindrome(String str)
{
if (str.length()==1 || str.length == 0)
return true;
char c1 = str.charAt(0);
char c2 = str.charAt(str.length() - 1);
if (str.length() == 2)
{
if (c1 == c2)
return true;
else
return false;
}
if (c1 == c2)
return palindrome(str.substring(1,str.length() - 1));
else
return false;
}
My two cents. It's always nice to see the different ways people solve a problem. Of course this is not the most efficient algorithm memory or speed wise.
public static boolean isPalindrome(String s) {
if (s.length() <= 1) { // got to the middle, no need for more checks
return true;
}
char l = s.charAt(0); // first char
char r = s.charAt(s.length() - 1); // last char
if (l == r) { // same char? keep checking
String sub = s.substring(1, s.length() - 1);
return isPalindrome(sub);
}
return false;
}
The simplest way to check palindrome.
private static String palindromic(String word) {
if (word.length() <= 1) {
return "Polidramic";
}else if (word.charAt(0) != word.charAt(word.length() - 1)) {
return "Not Polidramic";
}
return palindromic(word.substring(1, word.length() - 1));
}
Related
How check if a String contains only one specific character?
Eg:
On the String square/retrofit and square/retrofit/issues I need to check if the String has more than one / character.
square/retrofit/issues need to be false because have more than one / character and square/retrofit need to be true.
The string can have numbers.
You do not need regex. Simple indexOf and lastIndexOf methods should be enough.
boolean onlyOne = s.indexOf('/') == s.lastIndexOf('/');
EDIT 1
Of course, if / does not appear in given string above will be true. So, to avoid this situation you can also check what is returned index from one of these methods.
EDIT 2
Working solution:
class Strings {
public static boolean availableOnlyOnce(String source, char c) {
if (source == null || source.isEmpty()) {
return false;
}
int indexOf = source.indexOf(c);
return (indexOf == source.lastIndexOf(c)) && indexOf != -1;
}
}
Test cases:
System.out.println(Strings.availableOnlyOnce("path", '/'));
System.out.println(Strings.availableOnlyOnce("path/path1", '/'));
System.out.println(Strings.availableOnlyOnce("path/path1/path2", '/'));
Prints:
false
true
false
Or if you'd like to use a bit more modern approach with streams:
boolean occursOnlyOnce(String stringToCheck, char charToMatch) {
return stringToCheck.chars().filter(ch -> ch == charToMatch).count() == 1;
}
Disclaimer: This is not supposed to be the most optimal approach.
A bit more optimized approach:
boolean occursOnlyOnce(String stringToCheck, char charToMatch) {
boolean isFound = false;
for (char ch : stringToCheck.toCharArray()) {
if (ch == charToMatch) {
if (!isFound) {
isFound = true;
} else {
return false; // More than once, return immediately
}
}
}
return isFound; // Not found
}
How do I remove a target character from string using RECURSION?
I know it begins like:
public static String removeChar(String str, char target) {
if (str.length() == 0) {
return str;
} else {
if (str.charAt(0) == target) {
return removeChar(/*what goes in here?*/)
}
return removeChar(/*what goes in here?*/)
}
}
thank you!!
The idea is that if the first character is equal to the target character, you simply return the result of removeChar() applied on the rest of the String (i.e. the String without the first character), which removes the first character.
On the other hand, if the first character is not equal to the target character, you return a String starting with the original first character and ending with the result of applying removeChar() on the rest of the String.
public static String removeChar(String str, char target) {
if(str.length() == 0) {
return str;
} else {
if(str.charAt(0) == target) {
// remote the first character, and apply the recursive method to
// the rest of the String
return removeChar(str.substring(1),target);
} else {
// don't remote the first character, and apply the recursive method to
// the rest of the String
return str.charAt(0) + removeChar(str.substring(1),target);
}
}
}
You could use the following code inside the else-block:
if(str.charAt(0) == target) {
return removeChar(str.substring(1), target);
}
return charAt(0) + removeChar(str.substring(1), target);
But I don't see a need to use recursion here, you could just use
str.replace(target, '');
You check the index of the 1st occurrence of the char and remove it from that position:
public static String removeChar(String str, char target) {
int index = str.indexOf(target);
if (index < 0)
return str;
else {
return removeChar(str.substring(0, index) + str.substring(index + 1), target);
}
}
public static void main(String[] args) {
String str = "0123045607890";
System.out.println(removeChar(str, '0'));
}
will print:
123456789
I suggest this solution.
function isLetter(str) {
return str.length === 1 && str.match(/[A-Z]/i);
}
function removeLetters(str) {
//console.log(str);
let val = str.substr(0, 1);
console.log(val);
if (isLetter(val)) {
return removeLetters(str.substr(1))
} else {
console.log("Return", str);
return str;
}
}
I tried searching for solutions, but all that I have found are for strings. What I am trying to do is to check if a character array inputted by the user is a palindrome. Here's what I have so far:
public static boolean palCheck(char[] a, int index, int start) {
if (a[start] != a[index]){
return false; //base case
}
else if(a[start+1] == a[index]){
palCheck (a, index-1, start+1);
return true; //recursive step
}
else
return false;
}
It always returns true if the first and last elements of the array is the same. Where did I go wrong? Thanks in advance!
Another approach. Recursion.
public static boolean palCheck(char[] array) {
return palCheck(array, 0, array.length-1);
}
public static boolean palCheck(char[] array, int startIndex, int endIndex) {
if (startIndex >= endIndex)
return true;
else
if (array[startIndex] == array[endIndex])
return palCheck(array, startIndex+1, endIndex-1);
else
return false;
}
I have written two methods to be able to call it this way
String input = "AKKA";
palCheck(input.toCharArray());
instead of
String input = "AKKA";
palCheck(input.toCharArray(), 0, input.length());
What is quicker to write for String input:
boolean isPalindrome = new StringBuilder(input).reverse().equals(input);
You are returning true in your equals situation, not your recursive solution (which is being discarded). You will also want to check for when the indices are out of range or when they are equal so your function terminates when you've finished confirming it's a palindrome.
edit:
public static boolean palCheck(char[] a, int index, int start) {
if (index <= start) {
return true;
}
if (a[start] != a[index]){
return false; //base case
} else {
return palCheck (a, index-1, start+1); //recursive step
}
}
Add a check
if(index<=start)
return true;
Also change
if(a[start+1] == a[index])
to
if(a[start] == a[index])
Write a recursive method called isReverse("word1", "word2") that accepts two Strings as parameters and returns true if the two Strings contain
the same sequence of characters as each other but in opposite order, ignoring case, and returning false otherwise.
For example, the call of:
isReverse("Desserts", "Stressed")
would return true. [So eat desserts when you are stressed?]
Null, empty and one letter strings are also to return true (if both parameters are the same value).
This is homework and I am having trouble making this code work appropriately. It returns true no matter what I do.
public static boolean isReverse(String word1, String word2)
{
if(word1 == null || word2 == null)
{
if(word1!= null && word2 != null)
{
return false;
}
return false;
}
else if(word1.length() == word2.length())
{
String firstWord = word1.substring(0, word1.length());
String secondWord = word2.substring(word2.length()-1);
if (firstWord.equalsIgnoreCase(secondWord))
{
return isReverse(word1.substring(0, word1.length()), word2.substring(word2.length() - 1));
}
}
return true;
}
First, you have this set so that it will only return false if both words are null; If they are not null you're re-calling the method(in the event that the length is equal), which will return true.
private static boolean isReverse(String a, String b) {
// make sure the strings are not null
if(a == null || b == null) return false;
// If the lengths are not equal, the strings cannot be reversed.
if(a.length() != b.length()) {
return false;
}
// Convert string b to an array;
char[] bArray = b.toCharArray();
// Create an array to write bArray into in reverse.
char[] copy = new char[bArray.length];
// Iterate through bArray in reverse and write to copy[]
for(int i = bArray.length; i < 0; i--) {
copy[bArray.length - i] = bArray[i];
}
// Convert copy[] back into a string.
String check = String.valueOf(copy);
// See if they reversed string is equal to the original string.
if(check.equalsIgnoreCase(a)) {
return true;
} else {
return false;
}
}
You are saying
if (firstWord.equalsIgnoreCase(secondWord))
{
return isReverse(word1.substring(0, word1.length()), word2.substring(word2.length() - 1));
}
which is OK. But what if firstWord does not equal second word
It falls through and returns true.
You need to add an
else
return false;
I will also add that your null checking will not work.
if(word1!= null && word2 != null)
{
return false;
}
Is not useful because you are already in an if that only happens when word1 or word2 is null. So they can't be null and null here.
It would work if you made it
if(word1 == null && word2 == null)
{
return true;
}
Is this an exercise? Recursion doesn't seems to be the best option here. Anyway, you're just trimming one word, why? You must trim both words if you expect to compare each char in each recursive call. And you're not even passing the trimmed words as parameter to the recursive function!
The basic thing you're missing is a base case. When the recursion must return? In your case, you're reducing each string size at each step of recursion, so you must have a base case to check if the size is one.
Hope that this code clear your mind:
public static boolean isReverse(String word1, String word2) {
if (word1 == null || word2 == null) {
return false;
}
if (word1.length() == 1 && word2.length() == 1) {
//Used equals just for fast compare
return word1.equals(word2);
} else if (word1.length() == word2.length()) {
if (word1.charAt(0) == word2.charAt(word2.length() - 1)) {
String firstWord = word1.substring(1, word1.length());
String secondWord = word2.substring(0, word2.length() - 1);
System.out.printf("Trimmed %s, %s to %s, %s\n", word1, word2, firstWord, secondWord);
return isReverse(firstWord, secondWord);
} else {
//Characters didn't matched
return false;
}
} else {
//Lenght doesn't match
return false;
}
}
First I have reversed one of the string(i took word1) using recursion.then compared to second string if both strings are equal result set to true.
public static boolean isReverse(String word1, String word2)
{
boolean result = false;
//check null to avoid null pointer exception
if(word1 == null | word2 == null){
result = false;
}else if(word1.length() == word2.length()){
word1 = reverseString(word1);
if(word1.equalsIgnoreCase(word2)){
result = true;
}
}
return result;
}
static String reverse = "";
public static String reverseString(String str){
if(str.length() == 1){
reverse+=str;
} else {
reverse += str.charAt(str.length()-1)
+reverseString(str.substring(0,str.length()-1));
}
return reverse;
}
Compare three boolean values and display the first one that is true.
Hey guys, I am trying to write a program that compares three boolean values and displays the first true one. I am comparing three words for their length, and it will display the longest. The error that I am getting is that my else tags aren't working. Take a look at the code.
//Check which word is bigger
if (len1 > len2)
word1bt2 = true;
if (len2 > len3)
word2bt3 = true;
if (len1 > len3)
word1bt3 = true;
//Check which word is the longest
if (word1bt2 == true && word1bt3 == true);
System.out.println(wor1);
else if (word2bt3 == true);
System.out.println(wor2);
else System.out.println(wor3);
I have set boolean values for word1bt2, word2bt3 and word1bt3. In eclipse, I am getting a syntax error under the elses in my code above. Any help would be great!
if (word1bt2 == true && word1bt3 == true);
Is wrong, you need to remove the semicolon:
if (word1bt2 == true && word1bt3 == true)
Same for the elses
else (word2bt3 == true);
Is wrong too, it should be
else if (word2bt3 == true)
Side note: boolean values can be used as condition, so your if statements should be
if (word1bt2 && word1bt3) // The same as if (word1bt2 == true && word1bt3 == true)
How to compare three boolean values?
Dont!
If you find yourself needing to compare three variable you may as well cater for any number of variables immediately - there's no point hanging around - do it properly straight away.
public String longest(Iterator<String> i) {
// Walk the iterator.
String longest = i.hasNext() ? i.next() : null;
while (i.hasNext()) {
String next = i.next();
if (next.length() > longest.length()) {
longest = next;
}
}
return longest;
}
public String longest(Iterable<String> i) {
// Walk the iterator.
return longest(i.iterator());
}
public String longest(String... ss) {
// An array is iterable.
return longest(ss);
}
Remove the ; and change it with brackets {}.
if (word1bt2 && word1bt3) {
System.out.println(wor1);
} else if (word2bt3) {
System.out.println(wor2);
} else {
System.out.println(wor3);
}
Issue with the else blocks: use {} insteaad of () to enclose instructions...
Remove the ; at the first if!!!!! - Quite common mistake, with very puzzling results!
//Check which word is the longest
if (word1bt2 == true && word1bt3 == true) { //leave ; and always add bracket!
System.out.println(wor1);
}
else if(word2bt3 == true)
{
System.out.println(wor2);
}
else {
System.out.println(wor3);
}
if you need a condition in an else branch, you have to use if again - plain else won't have such a feature...
ALWAYS use brackets for bodies of if statements, loops, etc!!!
Be extremely careful NOT to use ; in the lines that don't behave well with it:
if statements
for loops
while() {...} loops' while statement
try this, if lenght are equal then s1 is considered as Bigger. Also i have not added null check
public class Test {
public static void main(String[] args) {
String word1 = "hi";
String word2 = "Hello";
String word3 = "Hell";
String Bigger = null;
if(word1.length() >= word2.length() && word1.length() >= word3.length() ){
Bigger = word1;
}else if(word2.length() >= word1.length() && word2.length() >= word3.length()){
Bigger = word2;
}else if(word3.length() >= word2.length() && word3.length() >= word1.length()){
Bigger = word3;
}
System.out.println(Bigger);
}
}