Why doesn't my palindrome program work correctly? It always returns false, and I can't tell why.
Here is my code:
public static boolean isPalindromIterative(String string) {
int a = 0;
int b = string.length() - 1;
while (b > a) {
if (a != b) {
return false;
}
a++;
b--;
}
return true;
}
You are comparing values of a and b which aren't the same when you start comparing and hence you get false from your method.
In your if condition, Change it to be string.charAt(a) != string.chatAt(b)
When you say
while (b > a) {
if (a != b) {
It's clear that a is not equal to b (or the loop wouldn't be entered). Going by context, I believe you wanted to compare the characters in the String. I would use String.toCharArray() to get a char[] and do something like
char[] chars = string.toCharArray();
while (b > a) {
if (chars[a] != chars[b]) {
If b > a in your code while (b > a), then a doesn't equal to b in your code if (a != b).
To check given string is palindrome or not in java simply use StringBuilder class reverse() method and check with given string.
public static boolean isPalindromIterativeStringBuilder(String string) {
StringBuilder sb = new StringBuilder(string);
sb.reverse(); //Reverse to the given string
return sb.toString().equalsIgnoreCase(string); //Check whether given string is equal to reverse string or not
}
This is also an iterative method.
I would be happy if I helped someone. ;)
public static boolean isPalindromeIterative(String string) {
String polindromCheck = string.toUpperCase();
for (int index = 0; index < polindromCheck.length(); index++) {
if (polindromCheck.charAt(index) != polindromCheck.charAt(string.length() - 1 - index)) {
return false;
}
}
return true;
}
Related
I've already read many previous questions here and elsewhere, but I haven't found what I need.
I need to write a recursive implementation of indexOf. The problem is that I can't use any local variables and have to give as input only a string and a char.
The method should return a value between 0 and the length of the string - 1 if the char has been found or -1 if it is not there.
I know the actual 'indexOf' allows you to search for a string too, but this method is simplified.
I tried this but it's quite stupid since I used the real indexOf:
public static int indexOf(String s, char c){
if(s.indexOf(c) < 0){ // I'd like to change this
return -1;
}
if (s.length() == 0) //base case #1
{
return -1;
}
else if (s.charAt(0) == c) //base case #2
{
return 0;
}
else {
return 1 + indexOf(s.substring(1), c);
}
}
I saw this in particular, but is it possibile to write it without variables? Thanks
If you don't want local variables, you need to do the recursion in an internal method.
Advantage is that it's a lot faster, since it doesn't have to create new String objects, and the logic is tail-recursive, if used with a language that optimizes that.
public static int indexOf(String s, char c) {
return indexOf0(s, c, 0);
}
private static int indexOf0(String s, char c, int index) {
if (index == s.length())
return -1;
if (s.charAt(index) == c)
return index;
return indexOf0(s, c, index + 1);
}
The answer that you linked seems to be a good one... I recommend simply replacing the instances of the variable used in it with the method call the variable stores.
Below I simply edit the code:
public static int indexOf(char ch, String str) {
// Returns the index of the of the character ch
if (str == null || str.equals("")) {
// base case: no more string to search; return -1
return -1;
} else if (ch == str.charAt(0)) {
// base case: ch is at the beginning of str; return 0
return 0;
}
return indexOf(ch, str.substring(1)) == -1 ? -1 : 1 + indexOf(ch, str.substring(1));
}
Example 1:
Input: S = "ab#c", T = "ad#c"
Output: true
Explanation: Both S and T become "ac".
Example 2:
Input: S = "ab##", T = "c#d#"
Output: true
Explanation: Both S and T become "".
Example 3:
Input: S = "a##c", T = "#a#c"
Output: true
Explanation: Both S and T become "c".
Example 4:
Input: S = "a#c", T = "b"
Output: false
Explanation: S becomes "c" while T becomes "b".
class Solution {
public boolean backspaceCompare(String S, String T) {
Stack<Character> stack1 = new Stack<Character>();
Stack<Character> stack2 = new Stack<Character>();
for(int i=0;i<S.length();i++){
if(S.charAt(i)!='#'){
stack1.push(S.charAt(i));
}else{
stack1.pop();
}
}
for(int j =0;j<T.length();j++){
if(T.charAt(j)!='#'){
stack2.push(S.charAt(j));
}else
stack2.pop();
}
if(stack1==stack2)
return true;
return false;
}
}
my output is false and answer should be true why is this not working?
The first mistake is pushing all the characters on the stack outside of the if statement.
Also you should check if stack is empty before removing items from it.
Otherwise EmptyStackException is thrown.
// stack1.push(S.charAt(i)); <-- remove this line
if (S.charAt(i)!='#') {
stack1.push(S.charAt(i));
}else if (!stack1.isEmpty()) { // <-- add this check
stack1.pop();
}
The second mistake is you can't use == to compare the contents of two stacks, use .equals method instead:
if(stack1.equals(stack2))
Answer by Joni correctly addresses the errors in the code, however there are some other issues I'd like to address:
You should use a helper method to eliminate repeating the same code.
You should use Deque instead of Stack. The javadoc says so.
Instead of using Stack/Deque, I'd recommend using StringBuilder, to prevent having to box the char values.
Something like this:
public boolean backspaceCompare(String s, String t) {
return applyBackspace(s).equals(applyBackspace(t));
}
private static String applyBackspace(String s) {
StringBuilder buf = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) != '#')
buf.append(s.charAt(i));
else if (buf.length() != 0)
buf.setLength(buf.length() - 1);
}
return buf.toString();
}
Your idea works, but it's expensive and unnecessary to copy the strings into stacks. If you work backwards from the end, no extra storage is necessary:
//given the string length or a valid character position, return
//the position of the previous valid character, or -1 if none
public static int previousCharPos(String s, int pos)
{
int bs=0; // number of backspaces to match
while(pos>0) {
--pos;
if (s.charAt(pos)=='#') {
++bs;
} else if (bs <= 0) {
return pos;
} else {
--bs;
}
}
return -1;
}
public static boolean backspaceCompare(String S, String T)
{
int spos = previousCharPos(S,S.length());
int tpos = previousCharPos(T,T.length());
while(spos >= 0 && tpos >= 0) {
if (S.charAt(spos) != T.charAt(tpos)) {
return false;
}
spos = previousCharPos(S,spos);
tpos = previousCharPos(T,tpos);
}
return spos == tpos;
}
What I have so far:
public boolean allSameLetter(String str)
{
for (int i = 1; i < str.length(); i++)
{
int charb4 = i--;
if ( str.charAt(i) != str.charAt(charb4))
{
return false;
}
if ( i == str.length())
{
return true;
}
}
}
Please excuse any inefficiencies if any; still relatively new to coding in general. Am I lacking some knowledge in terms of using operators and .charAt() together? Is it illogical? Or is my error elsewhere?
Using regex:
return str.matches("^(.)\\1*$");
Using streams:
str.chars().allMatch(c -> c == str.charAt(0));
Other:
return str.replace(String.valueOf(str.charAt(0), "").length() == 0;
You can follow the below steps:
(1) Get the first character (i.e., 0th index)
(2) Check the first character is the same with subsequent characters, if not return false (and comes out from method)
(3) If all chars match i.e., processing goes till the end of the method and returns true
public boolean allSameLetter(String str) {
char c1 = str.charAt(0);
for(int i=1;i<str.length;i++) {
char temp = str.charAt(i);
if(c1 != temp) {
//if chars does NOT match,
//just return false from here itself,
//there is no need to verify other chars
return false;
}
}
//As it did NOT return from above if (inside for)
//it means, all chars matched, so return true
return true;
}
As Andrew said, you are decreasing i within your for loop. You can fix this by changing it to int charb4 = i - 1;. As for making your code more efficient you could condense it down to this.
public boolean allSameLetter(String str) {
for(char c : str.toCharArray())
if(c != str.charAt(0)) return false;
return true;
}
Comment if you don't understand a part of it :)
public boolean allSameLetter(String str)
{
for (int i = 1; i < str.length() -1; i++)
{
if ( str.charAt(i) != str.charAt(i+1))
{
return false;
}
}
return true
}
-1 is there since I am checking the current value in the array, then the next value in the array, thus I need to stop a place earlier.
If the loop if statement is never entered, it will make it far enough into the code to return true
You have to create a for loop that searches through the length of the String - 1. this way the program will not crash because of a 3 letter word with the program trying to get the 4th letter. This is what works for me:
public boolean allSameLetter(String str)
{
for(int i = 0; i< str.length()-1; i++){
if (str.charAt(i) != str.charAt(i+1)){
return false;
}
}
return true;
}
if((new HashSet<Character>(Arrays.asList(s.toCharArray()))).size()==1)
return true;
return false;
This should be enough
The bug is caused by
int charb4 = i--;
this line is equal to
int charb4 = i-1;
i=i-1;
Because of this, your loop will never stop.
The easiest way to fix this
public boolean allSameLetter(String str)
{
for (int i = 1; i < str.length(); i++)
{
if ( str.charAt(i) != str.charAt(i-1))
{
return false;
}
}
}
Consider 4 input fields A, B, C and D on a web surface. The user can fill any of these arbitrary. There are 16 combinations of how to fill these fields. The ones allowed are:
A B C D
-------
1 0 0 0
1 1 0 0
1 1 1 0
1 1 1 1
where 1 means not null and 0 means null.
I am using the MVC pattern with jsf. I don't want the logic to be in the view, but rather in the controller. What is the best way to check this in Java?
I implemented two solutions so far:
Solution 1:
#Override
public boolean isInputInvalid(Integer a, Integer b, Integer c, Integer d) {
if (isNotSet(a) && isNotSet(b) && isNotSet(c) && isNotSet(d) {
return true;
}
return (firstParameterDoesNotExistAndSecondDoesExist(a, b)) || (firstParameterDoesNotExistAndSecondDoesExist(b, c)) || (firstParameterDoesNotExistAndSecondDoesExist(c, d));
}
private boolean firstParameterDoesNotExistAndSecondDoesExist(Integer firstParameter, Integer secondParameter) {
return isNotSet(firstParameter) && !isNotSet(secondParameter);
}
private boolean isNotSet(Integer parameter) {
return parameter == null;
}
Solution 2:
public boolean isInputValid(Integer a, Integer b, Integer c, Integer d) {
if (exists(a) && !exists(b) && !exists(c) && !exists(d) || //
exists(a) && exists(b) && !exists(c) && !exists(d) || //
exists(a) && exists(b) && exists(c) && !exists(d) || //
exists(a) && exists(b) && exists(c) && exists(d)) {
return true;
}
return false;
}
private boolean exists(Integer level) {
return level != null;
}
Note:
The first methods checks if input is invalid, while the second checks if input is valid (note the names of the methods).
I wrote 16 unit test cases, which all run green with both versions.
Do you have any hints/tips/tricks on how to get the code even more readable?
Valid combinations are: 1000, 1100, 1110 and 1111
If you only care about readability:
public static List<String> validOptions = Arrays.asList("1000","1100","1110","1111");
public boolean isValid(Integer a, Integer b, Integer c, Integer d)
{
StringBuilder sb = new StringBuilder();
sb.append(a==null ? 0 : 1);
sb.append(b==null ? 0 : 1),
sb.append(c==null ? 0 : 1);
sb.append(d==null ? 0 : 1);
return validOptions.contains(sb.toString());
}
Note that this is not the fastest or cleanest solution (wastes some CPU and memory)
To solve this for an arbitrary number of parameters, pass in true or false (if not null / null) in this:
static boolean isValid(boolean... params) {
boolean set = true;
for (boolean param : params) {
if (!set && param) return false;
set = param;
}
return params[0];
}
Or much cooler (and IMHO readable), but less performant, use regex on the array's toString():
static boolean isValid(boolean... params) {
return Arrays.toString(params).matches("\\[true(, true)*(, false)*]");
}
which ever implementation you use, you would call it like:
if (isValid(a != null, b != null, c != null, d != null))
Not fancy but fast and simple:
static boolean isValid(boolean a, boolean b, boolean c, boolean d) {
return a && (b || !c) && (c || !d);
}
Call:
isValid(a != null, b != null, c != null, d != null);
I don't really understand why you need this. Rather than a method that tests if input is valid, it would be much better to only allow valid input in the first place.
// This method is private, so you can't call it with arbitrary arguments.
private void privateMethod(Integer a, Integer b, Integer c, Integer d) {
// do something();
}
public void method(int a) {
privateMethod(a, null, null, null);
}
public void method(int a, int b) {
privateMethod(a, b, null, null);
}
public void method(int a, int b, int c) {
privateMethod(a, b, c, null);
}
public void method(int a, int b, int c, int d) {
privateMethod(a, b, c, d);
}
The way to modify this to any number of arguments (not just 4) is to have a method with signature
public void method(int... a)
Then, if the length of the array passed is less than the required length, you can just use null for the remaining inputs.
If this does not address your problem, I think you should consider editing your question to give an example of your use case, because I suspect there is a better way to achieve what you require.
You could create a pattern with a two dimensional array.
The advantage is that it is easy to adjust, and add additional information to it.
Here is a tiny example with your conditions.
In the end all you have to read is the pattern that is initialized in the static block, which is quite easy to read.
// Every boolean array in a dimension represents a valid pattern
private static boolean[][] pattern;
static {
pattern = new boolean[4][4];
pattern[0] = new boolean[]{true, false, false, false};
pattern[1] = new boolean[]{true, true, false, false};
pattern[2] = new boolean[]{true, true, true, false};
pattern[3] = new boolean[]{true, true, true, true};
}
public static void main(String[] args) {
// Testing an invalid combination
System.out.println(test(new Integer[]{1,null,3,null}));
// Testing a valid combination
System.out.println(test(new Integer[]{1,2,3,null}));
}
private static boolean test(Integer[] input) {
// cast the input to a boolean array that can be compared to the pattern.
boolean[] arr = createArr(input);
for(int i = 0;i<pattern.length;++i) {
if(Arrays.equals(pattern[i], arr)) { // Check if the pattern exists in the list of valid pattern. If it exists, then this is a valid combination
return true;
}
}
// the loop never found a valid combination, hence it returns false.
return false;
}
// This is just a helping method to create a boolean array out of an int array. It casts null to true and !null to false.
private static boolean[] createArr(Integer[] input) {
boolean[] output = new boolean[input.length];
for(int i = 0;i<input.length; ++i) {
output[i] = input[i] != null;
}
return output;
}
Yet another solution. Involves more code but for me it's easier to understand:
boolean isInputInvalid(Object ... args) {
int notNullDataIndex = -1;
for (int i = args.length - 1; i >= 0; i--) {
if (args[i] != null) {
notNullDataIndex = i;
break;
}
}
if (notNullDataIndex < 0) return false;
for (int i = notNullDataIndex; i >= 0; i--) {
if (args[i] == null) return false;
}
return true;
}
Here is what I have for method lastIndexOf , ch is the character to match, and str is the source string.
public static int lastIndexOf(char ch, String str) {
// check for null string or empty string
if (str.length() == 0 || str == null) {
return -1;
}
int indexInRest = lastIndexOf(ch, str.substring(1));
char first = str.charAt(0);
// recursive call to find the last matching character
if (first == ch) {
return 1 + indexInRest; // this might not work properly
} else
return indexInRest;
}
If in my class' main method I call:
System.out.println(lastIndexOf('r', "recurse"));
System.out.println(lastIndexOf('p', "recurse"));
I got:
1
-1
The desired result is:
4
-1
Suggestion, please.
How about taking the functional approach..
public static int lastIndexOf(char ch, String str) {
if (str.charAt(str.length() - 1) == ch) { return str.length() -1; }
if (str.length() <= 1) { return -1; }
return lastIndexOf(ch, str.substring(0, str.length() - 1));
}
This must be homework because there would be no point to writing this method since String.lastIndexOf() exists in the API, and using recursion to do this going to be slow and use a lot of memory.
Here a hint. Right now your algorithm is chopping characters off the front ( substring(1) ) and comparing them. lastIndexOf() should start by removing characters at the back of the String looking for a match then quit when it finds one.
why not use String.lastIndexOf like this:
str.lastIndexOf(ch)
Use the String#lastIndexOf(int ch) implementation as a general guideline,
public int lastIndexOf(int ch) {
return lastIndexOf(ch, value.length - 1);
}
public int lastIndexOf(int ch, int fromIndex) {
if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
// handle most cases here (ch is a BMP code point or a
// negative value (invalid code point))
final char[] value = this.value;
int i = Math.min(fromIndex, value.length - 1);
for (; i >= 0; i--) {
if (value[i] == ch) {
return i;
}
}
return -1;
} else {
return lastIndexOfSupplementary(ch, fromIndex);
}
}
private int lastIndexOfSupplementary(int ch, int fromIndex) {
if (Character.isValidCodePoint(ch)) {
final char[] value = this.value;
char hi = Character.highSurrogate(ch);
char lo = Character.lowSurrogate(ch);
int i = Math.min(fromIndex, value.length - 2);
for (; i >= 0; i--) {
if (value[i] == hi && value[i + 1] == lo) {
return i;
}
}
}
return -1;
}
And this,
lastIndexOf(ch, value.length - 1);
value is the target String as a character array.
First, you should change to:
if (str == null || str.length() == 0) {
Because a NPE could raise if str is null
Add a deep paramater to your code like this:
public static int lastIndexOf(char ch, String str, int deep) {
And increment its value every recursive call
int indexInRest = lastIndexOf(ch, str.substring(1), deep++);
then, in the return sentence, add deep to your returned value:
return 1 + indexInRest + deep; // this might not work properly
Call the function the first time with deep = 0, or better yet, make the two parameter method lastIndexOf call the 3 parameters version of lastIndexOf with the deep parameter set to 0
You can also use Matcher in order to anticipate evolution of string analysis asked by your homework:
public int getlastMatch(String searchPattern,String textString) {
int index = -1;
Pattern pattern = Pattern.compile(searchPattern);
Matcher matcher = pattern.matcher(textString);
while(matcher.find()) {
index = matcher.start();
}
return index;
}
where textString may be your concerned character.
Thus returning the last occurence of a part of string within a string.