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();
}
Related
Here below is the code with HashMap implementation of Trie. But I am not sure how to implement the autocomplete part. I see how people have used LinkedList to implement Trie, but I want to understand with HashMap. Any help appreciated. I have pasted the code below for my Trie.
Is there a way to look for a prefix, then go to the end of the prefix and look for its children and return them back as strings? And if so, how to achieve using HashMap implementation. Or shouldn't I even do this with HashMap and go for LinkedList. And I am not sure, why one is better than the other?
public class TrieNode {
Map<Character, TrieNode> children;
boolean isEndOfWord;
public TrieNode() {
isEndOfWord = false;
children = new HashMap<>();
}
}
public class TrieImpl {
private TrieNode root;
public TrieImpl() {
root = new TrieNode();
}
// iterative insertion into Trie Data Structure
public void insert(String word) {
if (searchTrie(word))
return;
TrieNode current = root;
for(int i=0; i<word.length(); i++) {
char ch = word.charAt(i);
TrieNode node = current.children.get(ch);
if(node == null) {
node = new TrieNode();
current.children.put(ch, node);
}
current = node;
}
current.isEndOfWord = true;
}
// search iteratively
public boolean searchTrie(String word) {
TrieNode current = root;
for(int i=0; i < word.length(); i++) {
char ch = word.charAt(i);
TrieNode node = current.children.get(ch);
if(node == null) {
return false;
}
current = node;
}
return current.isEndOfWord;
}
// delete a word recursively
private boolean deleteRecursive(TrieNode current, String word, int index) {
if(index == word.length()) {
if(!current.isEndOfWord) {
return false;
}
current.isEndOfWord = false;
return current.children.size() == 0;
}
char ch = word.charAt(index);
TrieNode node = current.children.get(ch);
if(node == null) {
return false;
}
boolean shouldDeleteCurrentNode = deleteRecursive(node, word, index+1);
if(shouldDeleteCurrentNode) {
current.children.remove(ch);
return current.children.size() == 0;
}
return false;
}
// calling the deleteRecursively function
public boolean deleteRecursive(String word) {
return deleteRecursive(root, word, 0);
}
public static void main(String[] args) {
TrieImpl obj = new TrieImpl();
obj.insert("amazon");
obj.insert("amazon prime");
obj.insert("amazing");
obj.insert("amazing spider man");
obj.insert("amazed");
obj.insert("alibaba");
obj.insert("ali express");
obj.insert("ebay");
obj.insert("walmart");
boolean isExists = obj.searchTrie("amazing spider man");
System.out.println(isExists);
}
}
I was in hurry finding some other solution here, but this is
interesting question.
Answering this-
Is there a way to look for a prefix, then go to the end of the prefix
and look for its children and return them back as strings?
Yes, why not, if you have prefix ama ,now go to your searchTrie method, and when you are done and out of the loop. then, you have current variable pointing to a(last character from ama)
you can then write a method as below -
public List<String> getPrefixStrings(TrieNode current){
// DO DFS here and put all character with isEndOfWord = true in the list
// keep on recursing to this same method and adding to the list
// then return the list
}
For my CS class, I had to create a boolean function isBalanced(String x) that takes a string and evaluates the amount of brackets/parentheses and returns true if the brackets match up to its pair (e.g; { is a pair of }, ( is a pair of ), [ is a pair of ], etc.). The function would return true if the brackets correctly matched up, false if otherwise. For clarification, MyStack() is my own implementation of the Java stack interface if you are wondering what that Object was.
Examples of how the code would work and return:
{A(B[C])D} would return true.
{A(B[C)]D} would return false.
The problem in my code is a logic error. For some reason, my function is returning true if there is a missing bracket, which should return false.
{A(B)C would return false, but my code reads it as true. Do you have any solutions that would help my code work properly? Thanks!
Balancer.java
public static boolean isBalanced(String x) {
MyStack<String> stack = new MyStack();
if (x.substring(0,1).equals("}") || x.substring(0,1).equals(")") || x.substring(0,1).equals("]")) {
return false;
}
for (int i=0; i<x.length(); i++) {
if (x.substring(i,i+1).equals("{") || x.substring(i,i+1).equals("(") || x.substring(i,i+1).equals("[")) {
stack.add(x.substring(i,i+1));
}
if (x.substring(i,i+1).equals("}") || x.substring(i,i+1).equals(")") || x.substring(i,i+1).equals("]")) {
if (x.substring(i,i+1).equals("}") && stack.peek().equals("{")) {
stack.pop();
} else if (x.substring(i,i+1).equals(")") && stack.peek().equals("(")) {
stack.pop();
} else if (x.substring(i,i+1).equals("]") && stack.peek().equals("[")) {
stack.pop();
} else {
return false;
}
}
}
return true;
}
This file, labeled Main.java, is just a tester. I have omitted the other cases where the code works. The reason why the function should return false is that there is a missing } which should be at the end, but there is none, yet my function returns true for some reason.
Main.java
public static void main(String[] args) {
...
String test4 = "{AA[B(CDE{FG()T})V]";
System.out.println("Missing final close (empty stack case)");
System.out.println("Should be false, is: " + Balancer.isBalanced(test4)); // does not work
}
You have a series of conditions that only pop the stack if a matching pair of brackets are found. I think you're overcomplicating things - if an opening bracket is found, push it to the stack. If a closing parenthesis is found, pop the stack and make sure that they match. E.g.:
private static final Map<Character, Character> CLODSE_TO_OPEN = new HashMap<>();
static {
CLODSE_TO_OPEN.put(')', '(');
CLODSE_TO_OPEN.put(']', '[');
CLODSE_TO_OPEN.put('}', '{');
}
public static boolean isBalanced(String x) {
Stack<Character> stack = new Stack<>();
for (int i = 0; i < x.length(); ++i) {
char c = x.charAt(i);
if (CLODSE_TO_OPEN.containsValue(c)) {
stack.push(c);
} else if (CLODSE_TO_OPEN.containsKey(c)) {
try {
if (!CLODSE_TO_OPEN.get(c).equals(stack.pop())) {
return false;
}
} catch (EmptyStackException e) {
return false;
}
}
}
return stack.isEmpty();
}
public class CheckPalindromeLL {
public static void main(String args[])
{
Link head=null;
Link l1=createLinkList1(head);
Link l2=l1;
System.out.println("first linklist");
display(l1);
System.out.println("reveresed linklist");
Link rev=reverse(l1);
Link rev2=rev;
display(rev2);
System.out.println("IS PALINDROME");
compare(l1,rev);
}
private static Link reverse(Link l11) {
Link l12=l11;
// TODO Auto-generated method stub
Link nextp;
Link curr=l12;
Link prevp=null;
while(curr!=null)
{
nextp=curr.next;
curr.next=prevp;
prevp=curr;
curr=nextp;
}
return prevp;
}
private static boolean compare(Link d1, Link d2) {
boolean flag=true;
while((d1!=null) && (d2!=null)&& flag)
{
if(d1.num!=d2.num)
{ System.out.println("not same ");
flag=false;
break;
}
else
{
System.out.println("list:"+d1.num);
System.out.println("rev:"+d2.num);
System.out.println(" same");
d1=d1.next;
d2=d2.next;
}
}
System.out.println("printing flag"+flag);
return flag;
}
private static Link createLinkList1(Link head) {
// TODO Auto-generated method stub
Link firstlink=head;
Link newLink = null;
Scanner reader = new Scanner(System.in);
System.out.println("Enter a number: ");
int x[]={1,2,3,1};
for(int i=0;i<x.length;i++)
{
newLink=new Link(x[i]);
newLink.next=firstlink;
firstlink=newLink;
}
head= firstlink;
return newLink;
}
public static void display(Link start)
{
Link s1=start;
while(s1!=null)
{
System.out.println(s1.num);
s1=s1.next;
}
}
}
Comparing linkedlist and reverse of linkedlist but cannot compare second element.It just check first element of original and reverse linkedlist and give answer on the basis of first element only.Am i missing something??
Here's an ASCII-art depiction of what your list (singular) looks like at each step. I've omitted the superfluous statements and print statements:
Link l1=createLinkList1(head);
l1-+
|
V
1 -> 2 -> 3 -> 1 -> null
Link rev=reverse(l1);
rev------------------+
|
l1-+ |
| |
V V
null <- 1 <- 2 <- 3 <- 1
compare(l1,rev);
You only ever create one list and one set of nodes not two. When you reverse() it you rearrange the pointers but leave l1 pointing to what used to be the first element but is now the last one.
You need to create a complete copy of the original list - in reverse order. This should do the trick:
private static Link reverse(Link l)
{
Link result = null;
while(l != null)
{
Link ll = new Link(l.value);
ll.next = result;
result = ll;
l = l.next;
}
return result;
}
Just as addition: If you have a doubly linked list (for the case you are willing to adapt your implementation...), you can easily check for palindromes without creating a reversed copy:
private static boolean isPalindrome(Link head, Link tail)
{
if(head == null)
{
return true; // arguable, if empty list is palindrome or not...
}
while(head != tail)
{
if(head.value != tail.value)
{
return false;
}
head = head.next;
if(head == tail) // need this for even number of list elements
{
break;
}
tail = tail.previous;
}
return true;
}
EDIT
Just a gimmick: Checking palindrome without duplicating the list (recursive):
private static boolean isPalindrome(Link head)
{
return head == null ? true : isPalindrome(new Link[] { head }, head);
}
private static boolean isPalindrome(Link[] head, Link tail)
{
if(tail.next != null)
{
if(!isPalindrome(head, tail.next))
{
return false;
}
head[0] = head[0].next;
}
return head[0].value == tail.value;
}
In order to check if a LinkedList is palindrome you can use the following code:
Note that java.util.LinkedList is a doubly linked list.
public class Palindrome<T extends Comparable>{
public boolean isPalindrome(LinkedList<T> list){
Iterator<T> iterator = list.iterator();
Iterator<T> reverseIterator = list.descendingIterator();
while(iterator.hasNext()&&reverseIterator.hasNext()){
if(!iterator.next().equals(reverseIterator.next())){
return false;
}
}
return true;
}
}
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.
Full disclosure: this is for an assignment, so please don't post actual code solutions!
I have an assignment that requires me to take a string from the user and pass it into a stack and a queue, then use those two to compare the chars to determine if the string is a palindrome. I have the program written, but there appears to be some logic error somewhere. Here's the relevant code:
public static void main(String[] args) {
UserInterface ui = new UserInterface();
Stack stack = new Stack();
Queue queue = new Queue();
String cleaned = new String();
boolean palindrome = true;
ui.setString("Please give me a palindrome.");
cleaned = ui.cleanString(ui.getString());
for (int i = 0; i < cleaned.length(); ++i) {
stack.push(cleaned.charAt(i));
queue.enqueue(cleaned.charAt(i));
}
while (!stack.isEmpty() && !queue.isEmpty()) {
if (stack.pop() != queue.dequeue()) {
palindrome = false;
}
}
if (palindrome) {
System.out.printf("%s is a palindrome!", ui.getString());
} else
System.out.printf("%s is not a palindrome :(", ui.getString());
stack.dump();
queue.clear();
}
public class Stack {
public void push(char c) {
c = Character.toUpperCase(c);
Node oldNode = header;
header = new Node();
header.setData(c);
header.setNext(oldNode);
}
public char pop() {
Node temp = new Node();
char data;
if (isEmpty()) {
System.out.printf("Stack Underflow (pop)\n");
System.exit(0);
}
temp = header;
data = temp.getData();
header = header.getNext();
return data;
}
}
public class Queue {
public void enqueue(char c) {
c = Character.toUpperCase(c);
Node n = last;
last = new Node();
last.setData(c);
last.setNext(null);
if (isEmpty()) {
first = last;
} else n.setNext(last);
}
public char dequeue() {
char data;
data = first.getData();
first = first.getNext();
return data;
}
}
public String cleanString(String s) {
return s.replaceAll("[^A-Za-z0-9]", "");
}
Basically, when running my code through the debugger in Eclipse, my pop and dequeue methods appear to only select certain alphanumerics. I am using replaceAll("[^A-Za-z0-9]", "") to "clean" the user's string of any nonalphanumeric chars (!, ?, &, etc.). When I say it only selects certain chars, there doesn't seem to be any pattern that I can discern. Any ideas?
Your general algorithm works properly, assuming your queue and stack are correct (i tried this using the Deque implementations found in the jdk). Since your assignment involves the datastructures, i've pretty much just took your main logic and replaced the datastructures with ArrayDequeue, so I don't feel like i'm answering this for you.
String word = "ooffoo";
word = word.replaceAll("[^A-Za-z0-9]", "");
Deque<Character> stack = new ArrayDeque<Character>(word.length());
Deque<Character> queue = new ArrayDeque<Character>(word.length());
for (char c : word.toCharArray()) {
stack.push(c);
queue.add(c);
}
boolean pal = true;
while (! stack.isEmpty() && pal == true) {
if (! stack.pop().equals(queue.remove())) {
pal = false;
}
}
System.out.println(pal);
I'd recommend using a debugger to see exactly what was being compared, or at the very least spit out some print lines:
while (!stack.isEmpty() && !queue.isEmpty()) {
Character sc = stack.pop();
Character qc = queue.dequeue();
System.out.println(sc + ":" + qc);
if (sc != qc) {
palindrome = false;
}
}