Comparing items in a stack - java

I am trying to compare two seperate stacks to see if they are the same or not. I have a loop iterate through each object in each stack and compare both objects. What I want to happen is if they are equal, continue the loop and return true. If they are not equal at any given point, break the loop and return false. This is what I have written:
public boolean isPalindrome (Stack a, Stack b) {
Object temp1;
Object temp2;
boolean answer;
for (int i = 0; a.size() > 0; i++) {
temp1 = a.pop();
temp2 = b.pop();
if (temp1 != temp2) {
answer = false;
}
else {
answer = true;
}
}
return answer;
}
What I see happening in this is that I have a boolean, and through each loop that boolean is assigned a value depending on what the objects are, then at the end of the loop, return that boolean in its most recent state. No matter what I initialize the variable to, its like the loop does absolutely nothing to it. Can you not modify or return a boolean in a loop? What would be the better way to go about this instance? I have looked at tons of other posts for similar issues, but most of them seem to be trying something a little different ad I would like to stick as true to my original ideas as possible, I just need to know what I am doing wrong. Any suggestions would help greatly. Thanks!

The basic idea that you can return false (which breaks method execution) once you find stacks are not equal. Otherwise return true:
public boolean isPalindrome (Stack a, Stack b) {
if (a.size() != b.size()) {
return false;
}
while (a.size() > 0) {
if (!a.pop().equals(b.pop())) {
return false;
}
}
return true;
}

public boolean isPalindrome (Stack a, Stack b) {
Object temp1;
Object temp2;
boolean answer = true;
for (int i = 0; a.size() > 0; i++) {
temp1 = a.pop();
temp2 = b.pop();
if (temp1 != temp2) {
answer = false;
break;
}
}
return answer;
}

You need to place a return statement when you find a false item -- else, you're simply returning the boolean found in the last iteration of your loop.
public boolean isPalindrome (Stack a, Stack b) {
Object temp1;
Object temp2;
boolean answer;
for (int i = 0; a.size() > 0; i++) {
temp1 = a.pop();
temp2 = b.pop();
if (temp1 != temp2) {
answer = false;
return answer;
}
else {
answer = true;
}
}
return answer;
}

My suggestion:
public boolean isPalindrome (Stack a, Stack b) {
if (a.size() != b.size()) return false;
while (a.size() > 0) {
if (a.pop() != b.pop()) {
return false;
}
}
return true;
}

You should put a break statement in just after answer is set to false. Without this, you are returning false only if the last items are not equal.
Quick note: I would also add a check for the case that the two stacks are not the same size.

Related

How to check to see if the top two elements of the stack exists?

I'm working with a Java Stack, and I want to know whether or not if the the stack has at least 2 items on top. I'm limited to just the methods in Stack and can't use things like .add().
My current problem is when the value of an element is 0. I have to deal with both positive, negative, and 0 ints. Here is my code for the method in question:
public static <E> boolean hasTwoElements(Stack<E> stack) {
int temp1 = 0;
int temp2 = 0;
boolean happened = false;
if (!stack.isEmpty()) {
//check if the assignment is success
happened = ((temp1 = (java.lang.Integer) stack.pop()) != 0)
&& ((temp2 = (java.lang.Integer) stack.pop()) != 0);
if (happened) { //if the 2 assignments happened
stack.push((E) new Integer(temp2)); //reverse order b/c popped in order
stack.push((E) new Integer(temp1));
return true;
}
}
return false;
}
To be more specific, I need to know whether an assignment succeeds or not.
If you truly can use only methods that are declared on the Stack class, and not methods inherited from parent class, then do it like this:
public static <E> boolean hasTwoElements(Stack<E> stack) {
if (stack.empty())
return false;
E top = stack.pop();
boolean hasTwo = ! stack.empty();
stack.push(top);
return hasTwo;
}
How about:
public static <E> boolean hasTwoElements(Stack<E> stack) {
return (stack.size() >= 2);
}
See Stack.size()

Trying to compare the contents two Iterators, how?

EDIT: With your help I managed to fix my problem. I have edited my code to now show how I had to have it set up to get it working.
Currently I am having trouble coding a part which compares the content of two iterators. As part of the requirements for my assignment, I need to use a linkedlist to store the individual characters of the entered String. I have gotten to the point where I have two iterators which would contain the input one way and the reverse way.
String palindrom = input.getText();
String [] chara = palindrom.split (""); //this is successfully splitting them, tested.
int length = palindrom.length( ); // length == 8
System.out.println (length); //can use this for how many checks to do?
LinkedList ll = new LinkedList(Arrays.asList(chara));
Iterator iterator = ll.iterator();
Iterator desIterator = ll.descendingIterator();
/*while(iterator.hasNext() ){
System.out.println(iterator.next() );
}
while(desIterator.hasNext() ){
System.out.println(desIterator.next() );
}*/
boolean same = true;
while(iterator.hasNext()){
if(!iterator.next().equals(desIterator.next())){
same = false;
break;
}
}
And using the System.out I can see that they are being stored correctly, but I don't know how to check if the iterators store the same contents. What would be one of the simplest methods to compare the two iterators or convert them into something I can compare? To clarify I want to verify they contain the same elements in the same order.
boolean same = true;
while(iterator.hasNext()){
if(!desIterator.hasNext() || !iterator.next().equals(desIterator.next())){
same = false;
break;
}
}
System.out.println(same);
You need to iterate over both iterators simultaneously, i.e. with one loop. Here is a general comparison function (0 when equal, < 0 when A < B, > 0 when A > B):
static <T extends Comparable<S>, S> int compare(Iterator<T> a, Iterator<S> b) {
while (a.hasNext() && b.hasNext()) {
int comparison = a.next().compareTo(b.next());
if (comparison != 0) {
return comparison;
}
}
if (a.hasNext())
return 1;
if (b.hasNext())
return -1;
return 0;
}
To just check if they are equal, this can be simplified:
static <T, S> boolean equals(Iterator<T> a, Iterator<S> b) {
while (a.hasNext() && b.hasNext()) {
if (!a.next().equals(b.next())) {
return false;
}
}
if (a.hasNext() || b.hasNext()) {
// one of the iterators has more elements than the other
return false;
}
return true;
}
Guava implements this as Iterators.elementsEqual.
In both answers throw NullPointerException, if iterator.next() == null. This method is more optimal.
public static boolean equals(Iterator i1, Iterator i2) {
if (i1 == i2) {
return true;
}
while (i1.hasNext()) {
if (!i2.hasNext()) {
return false;
}
if (!Objects.equals(i1.next(), i2.next())) {
return false;
}
}
if (i2.hasNext()) {
return false;
}
return true;
}

this method must return a result of type boolean

i am rewriting class string in java but for some method like startwith i have the same error. this is my code:
public boolean mystartwith(MyString s){
if(s.mylength() > this.mylength()){
return false;
}else{
for(int i=0 ; i<s.mylength() ; i++){
if(lesCaracteres[i] != s.lesCaracteres[i]){
return false;
}else{
return true;
}
}
}
}
and i have this error : "this method must return a result of type boolean"
If s is empty, for loop will be skipped - and your method won't return anything at all, hence the error. I'd rather add checking for this condition first.
Have to note, though, that given algorithm is flawed:
for (int i=0; i<s.mylength() ; i++){
if (lesCaracteres[i] != s.lesCaracteres[i]){
return false;
} else {
return true;
}
}
Ok, let's say I called this function with 'abc' string given as s, but instance wraps over the string 'acdef'. Guess what, your method will return true! The problem is that your loop breaks too soon: a value is returned right after checking for the first letter.
Actually, it should be written like this:
int sLength = s.myLength();
if (sLength == 0) {
return false;
// actually, it's for you to decide:
// technically each string begins with an empty string
}
if (sLength > this.mylength()) {
return false;
}
for (int i = 0; i < sLength; i++) {
if (lesCaracteres[i] != s.lesCaracteres[i]){
return false;
}
}
return true;
The key difference: true is returned only if for loop is walked over normally (i.e., exited via i < sLength condition. That, in turn, means, that all the characters of s string match those at the beginning of the string wrapped.
if(s.mylength() > this.mylength()){
return false;
}else{
for(int i=0 ; i<s.mylength() ; i++){
if(lesCaracteres[i] != s.lesCaracteres[i]){
return false;
}else{
return true;
}
}
return ____; //place true or false based on your condition
}
Suppose if(s.mylength() > this.mylength()) is not satisfied, then your code will go to the loop.
Now suppose the for loop doesn't loop, meaning s is empty. What will be returned?
Exactly! Nothing, since the loop will be skipped.
To fix this, you should return some boolean after the loop.
Java must guarantee that a boolean will be returned whatever the input, however there are conditions in which there is no return
public boolean mystartwith(MyString s){
if(s.mylength() > this.mylength()){
return false;
}else{
for(int i=0 ; i<s.mylength() ; i++){
if(lesCaracteres[i] != s.lesCaracteres[i]){
return false;
}else{
return true;
}
}
//what if s.mylength()==0 and the loop never runs?!
//therefore the code will get to here, and the method will end without a return
}
}
Note that java isn't "clever enough" to recognise that two ifs together make all posibilities. For example
boolean method(int a){
if (a>0){
return true;
}else{
if (a<=0){
return false;
}
//program can never get here, BUT java doesn't realise that
}
Still doesn't satisfy java because it imagines a scenario where both ifs are false
How to fix this depends on your specific program, but it's worth noting that the for loop will only run once at most before returning so is superfluos
You can to redefine your code like this:
public boolean mystartwith(MyString s){
if(s.mylength() > this.mylength()){
return false;
}else{
for(int i=0 ; i<s.mylength() ; i++){
if(lesCaracteres[i] != s.lesCaracteres[i]){
return false;
}else{
return true;
}
}
return false;
}
}

Checking to see if a string is a palindrome or not

I am very close to finishing my one practice problem that deals with a palindrome and a string parameter and I am stuck with the main method to call the method. Every time I compile my code it compiles, but then when I go to input data, it keeps on running and does not give me a result. Can anyone aid in me in what I need to do to get it to return the result? The problem just asks to create a method that checks if it is a palindrome, my main method to test it is what is giving me trouble.
This is my code:
import java.util.*;
public class TestisPalindrome
{
public static boolean isPalindrome(String str) {
int left = 0;
int right = str.length() -1;
while(left < right) {
if(str.charAt(left) != str.charAt(right)) {
return false;
}
}
left ++;
right --;
return true;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("Enter a string to see if it is a palindrome or not: ");
String st1 = scan.nextLine();
System.out.println(isPalindrome(st1));
}
}
right & left increment should be in while loop
while(left < right)
{
if(str.charAt(left) != str.charAt(right))
{
return false;
}
left ++;
right --;
}
You've created an infinite loop. You have a while loop, but never change the conditions.
while(left < right)
{
if(str.charAt(left) != str.charAt(right))
{
return false;
}
}
Assuming left < right when you start, this will never change.
You have lines to increment left and right, but your code will never reach those lines, since it never gets out of the while loop.
You are overthinking this. Look at StringBuffer:
StringBuffer input = new StringBuffer(str);
return str.equals(input.reverse()).toString);
Please note that there is a performance impact of your implementation:
while(left < right) { //multiply inner operations by n/2
if(str.charAt(left) != str.charAt(right)) { //three operations
return false;
}
//This need to be inside your while loop
left ++; //one operation
right --; //one operation
}
This leads to an O(n) = (n * 5) / 2. On the other hand, if you simply reverse a string, it's only O(n) = n in the worst case. This is not a significant impact, but can add up depending on how you're accessing this.
You can also solve it like this:
public static boolean isPalindrome (String str){
String convertedStr = "";
for (int i = 0; i <str.length(); i++){
if (Character.isLetterOrDigit(str.charAt(i)))
convertedStr += Character.toLowerCase(str.charAt(i));
}
if (convertedStr.equals(reverseString(convertedStr)))
return true;
else
return false;
} //End of isPalindrome
Here is the code I used to determine whether a string is Palindrome String or not:
private static boolean isPalindromeString(String str){
if (str == null)
return false;
int len = str.length();
for (int i=0; i<len/2 ; i++){
if (str.charAt(i) != str.charAt(len - i - 1)){
return false;
}
}
return true;
}
I hope this can help you.

Can someone suggest simplification for the code?

public boolean isPalindrome()
{
Stack myStack = new Stack();
for(Node current = head; current!=null; current = current.next)
{
if(!myStack.isEmpty())
{
if(myStack.peek()==current.data)
{
myStack.pop();
}else if(current.next!=null&&myStack.peek()==current.next.data)
{
continue;
}
else
{
myStack.push(current.data);
}
}else
{
myStack.push(current.data);
}
}
return myStack.isEmpty();
}
What I am doing here is using a stack to check whether a linked list is a palindrome. It works as expected only thing is I wanted to get rid of code duplication where the else condition has a push of the data onto the stack.
The algorithm is unfortunately not correct. For "abbaaa" it would report that that is a palindrome, although it isn't. Checking for palindromes without using the length is difficult.
abbaaa () -> push a
bbaaa (a) -> push b
baaa (ba) -> pop b
aaa (a) -> pop a
aa () -> push a
a (a) -> pop a
() -> palindrome
This is a somewhat classic problem. There are many ways to solve it in java. One of the easiest is this one:
boolean isPalindrome(String s) {
for (int i=0, len=s.length(); i<len/2; i++) {
if (s.charAt(i) != s.charAt(len-i-1)) return false;
}
return true;
}
(Strictly speaking, this is a rewrite rather than a refactoring; however, any rewrite that preserves method signatures can be seen as a refactoring... and it is certainly more efficient)
If all you want to do is remove the code duplication between the two else conditions then remove them entirely.
public boolean isPalindrome()
{
Stack myStack = new Stack();
for(Node current = head; current!=null; current = current.next)
{
if(!myStack.isEmpty())
{
if(myStack.peek()==current.data)
{
myStack.pop();
continue;
}else if(current.next!=null&&myStack.peek()==current.next.data)
{
continue;
}
}
myStack.push(current.data);
}
return myStack.isEmpty();
}
A simplification of functionality;
boolean isPalinDrome(String testString) {
return new StringBuffer(testString).reverse().toString().equals(testString);
}
This should provide same functionality without repeat. It is pointed out however that your algorithm doesn't seem to be correct.
public boolean isPalindrome()
{
Stack myStack = new Stack();
boolean doPush;
for(Node current = head; current!=null; current = current.next)
{
doPush = true;
if(!myStack.isEmpty())
{
if(myStack.peek()==current.data)
{
doPush = false;
myStack.pop();
}else if(current.next!=null&&myStack.peek()==current.next.data)
{
doPush = false;
continue;
}
}
if(doPush){
myStack.push(current.data);
}
}
return myStack.isEmpty();
}

Categories