i've to do write a code to solve this problem:
-Do the subtraction between two nodes p and q, where the substraction p - q is the list that contains all the elements that appear in p and not in q, knowing that p and q are ordered lists.
I tried to write a code and i know that it can't work...can you help me please to solve this problem? thank you very much!
class Node{
public int elem;
public Node next;
public Node(int elem, Node next){
this.elem = elem;
this.next = next;
}
}
public class Main{
public static Node diff(Node p, Node q){
if( p.elem == q.elem )
return diff(p.next, q.next);
else if(p.elem < q.elem){
return new Node (p.elem, diff(p.next, q.next));
else
return new Node(p.elem, diff(p.next, q.next));
}
public static void main(String[] args){
//.......
}
}
Your recursion never ends, since each return statement in your recursion method calls itself, which will lead your code to a Stack Overflow.
To solve this, you should decompose the problem.
First of all, let's find the base cases.
These are the cases where the recursion ends, and there's two for your problem:
If p == null, i.e. if the linked list contains no more items, then the work is done, there is nothing more to add to your result linked list.
if(p == null)
{
return null;
}
If q == null, then you should add all the remaining item in your linked list, i.e. the p node itself.
if(q == null)
{
return p;
}
There is 3 more possible cases, where recursion occurs:
If p.elem == q.elem then the node should not be added, and we should go to the next node for each linked list. Since the list are ordered, there is no way this node could be useful later.
if(p.elem == q.elem)
{
return diff(p.next, q.next);
}
If p.elem > q.elem the node might be useful, but we do not know yet. The next nodes of the second linked list might be equals, so we just skip to the next node for the second linked list.
if (p.elem > q.elem)
{
return diff(p, q.next);
}
There is only one case left, if p.elem < q.elem. This is it, we are sure that this node is absent from the second linked list, so we add a new node to our result.
return new Node(p.elem, diff(p.next, q);
Note that you do not need else statement in each case since there is a return in each of your cases.
Hope it helps!
Related
I need help with an assignement in java...so, I have a TreeNode class that looks like this...this is the way we were asked to do this so I am not allowed to change it.
class TreeNode{
int data;
TreeNode leftNode;
TreeNode rightNode;
public TreeNode(int data) {
this.data=data;
}
}
The problem is that i have to create a method int getNumOfNodes(TreeNode t) and will return the number of nodes in the structure.The thing is that i cannot figure out how to count the node with the value 9 only once since I am trying to use recursion for the left and right subtree and because this specific node has two parents it gets counted twice...Any ideas?
I am trying to create this structure(I am trying to explain it since I couldn;t post a pic)
5
/ \
7 12
\ / \
9 2
here is what I tried
int getNumOfNodes (TreeNode t){
if(t==null)
return 0;
return 1 + getNumOfNodes(t.leftNode) + getNumOfNodes(t.rightNode);
}
You can collect/find all the TreeNode objects first and put them in a Set. Since a Set cannot have duplicates, you add a node only once, even when you encountered it more than once. You can write a helper method like this:
private static Set<TreeNode> findAllNodes(TreeNode node) {
Set<TreeNode> nodes = new HashSet<TreeNode>();
nodes.add(node);
if (node.leftNode != null) {
Set<TreeNode> leftNodes = findAllNodes(node.leftNode);
nodes.addAll(leftNodes);
}
if (node.rightNode != null) {
Set<TreeNode> rightNodes = findAllNodes(node.rightNode);
nodes.addAll(rightNodes);
}
return nodes;
}
(untested pseudo code)
After that you can simply call size() to see how many nodes you have collected.
Set<TreeNode> allNodes = findAllNodes(t);
return allNodes.size();
Keep in mind that this pseudo code does not work for graphs with cycles.
When given an array of integers, I'm trying to change each element with the product of the integers before it.
For example, int[] array = {2,2,3,4}; is now: {2, 4, 12, 48};
I added each element to a LinkedList, and I'm trying to do this recursively.
This is what I have:
Node curr = list.getFirst();
product(curr);
public static void product(Node curr)
{
if(curr == null)
{
return;
}
else
{
int data = curr.getData() * curr.getNext().getData();
Node newNode = new Node(data);
curr.setNext(newNode);
// product(curr);
}
}
The first product works: {2,4}, but when I try to put in the recursion, I get a stackoverflow. Any suggestions??
Edit: So the reason that I'm either getting a stackoverflow or null pointer exception is because I'm updating the list, and then trying to get the next integer(but since there's only two elements in the list, there isn't a getNext()). I'm not sure how to fix this.
It looks like you were getting a bit tied up in the recursion. I modified your method to accept a Node along with the product from the previous iteration. At each step of the iteration I update the value in the already-existing List, so there is no need for using the new operator.
public static void product(Node curr, int value) {
if (curr == null) {
return;
}
else {
int data = value * curr.getData(); // compute current product
curr.setData(data); // update Node
product(curr.getNext(), data); // make recursive call
}
}
There are actually two issues with the code.
The recursion never ends, i.e. it is not actually moving to a smaller "subproblem" as the recursion is calling the same node again
and again.
After creating a new node and modifying the next we also need to connect the node "after" the next node otherwise the link will be
lost. Please check the below method which addresses both the issues.
Although I didn't do an excessive testing it is working for simple dataset.
Original List:
2->4->5->6->8->null
Multiplied List:
2->8->40->240->1920->null
public void product(Node curr) {
if (curr.getNext() == null) {
return;
} else {
int data = curr.getData() * curr.getNext().getData();
Node newNode = new Node();
newNode.setData(data);
Node nodeAfterNextNode = curr.getNext().getNext();
newNode.setNext(nodeAfterNextNode);
curr.setNext(newNode);
product(newNode);
}
}
It is because you call recursive method on the current node, so it is actually never move forward in the LinkedList. You can simply update the next node's data and call the recursive method on it. See the code below:
Node curr = list.getFirst();
product(curr);
public static void product(Node curr)
{
Node next = curr.getNext();
if(next == null)
{
return;
}
else
{
int data = curr.getData() * next.getData();
next.setData(data);
product(next);
}
}
I am trying to remove the second appearance of specific object in singly linked list.
I have this code for my Node:
public class Node {
Node next;
Object data;
public Node(Object _data)
{
next = null;
data = _data;
}
public Node(Object _data, Node _next)
{
next = _next;
data = _data;
}
public Object getData()
{
return data;
}
public void setData(Object _data)
{
data = _data;
}
public Node getNext()
{
return next;
}
public void setNext(Node _next)
{
next = _next;
}
}
And this is my function to remove:
public void removeSecondAppear(Object data)
{
Node temp = new Node(data);
Node current = head;
boolean found = false;
for(int i = 1; i < size(); i++)
{
current = current.getNext();
if(current.getData().equals(temp.getData()))
{
if(found == true)
{
// remove element
current.setNext(current.getNext().getNext());
listCount--;
break;
}
else if(found == false)
{
found = true;
}
}
}
}
For some reason it won't remove the element. The method to find it works fine, but I don't know why it won't remove the element. I have a similar function to remove element of specific index which works fine:
public boolean remove(int index)
{
if(index < 1 || index > size())
{
return false;
}
Node current = head;
for(int i = 1; i < index; i++)
{
if(current.getNext() == null)
{
return false;
}
current = current.getNext();
}
current.setNext(current.getNext().getNext());
listCount--;
return true;
}
I'm using the same methood, but it won't work in my method to remove the second appearance. Any help what I'm doin wron??
public int indexOf(Object data)
{
Node temp = new Node(data);
Node current = head.getNext();
for(int i = 0; i < size(); i++)
{
if(current.getData().equals(temp.getData()))
{
return i;
}
current = current.getNext();
}
return -1;
}
My implementation:
LinkedList LL = new LinkedList();
LL.add(1);
LL.add(2);
LL.add(3);
LL.add(4);
LL.add(4);
LL.add(5);
LL.removeSecondAppear("4");
My add method:
public void add(Object data)
{
Node temp = new Node(data);
Node current = head;
while(current.getNext() != null)
{
current = current.getNext();
}
current.setNext(temp);
listCount++;
}
My constructor:
public LinkedList()
{
head = new Node(null);
listCount = 0;
}
Your issue is going to be found here (in a couple places):
As you loop through, you will keep advancing current until you find two instances where the data is equal and then remove it. Your remove won't work because you're not actually removing the node you want, it's the next node you're removing, which won't necessarily be equal because you've already iterated over the list and lost the previous equal node.
current = current.getNext();
if(current.getData().equals(temp.getData()))
{
if(found == true)
{
// remove element
current.setNext(current.getNext().getNext()); // this isn't actually removing 'current'...
listCount--;
break;
}
else if(found == false)
{
found = true;
}
}
First thing, you're not resetting found after not finding an equal node.
After the if (equals) block, add:
else {
found = false;
}
Assuming you fix that, here's where you'd end up.
Take the following example:
[3] -> [4] -> [4] -> [5] -> [6]
In your algorithm you will iterate over each element in this list like so:
Pass 1:
found = false
[3] -> [4] -> [4] -> [5] -> [6]
^
current
found = false
Pass 2:
found = false
[3] -> [4] -> [4] -> [5] -> [6]
^
current
found = true
Pass 3:
found = true
[3] -> [4] -> [4] -> [5] -> [6]
^
current
When you get here, you are setting current.next to current.next.next, which is effectively removing [5] from the list, not 4. (consequently, this is also causing your NPE... consider the effects when you get to the end of the list and there is no next.next)
What you want to do is either find the index of your duplicate node and call your existing method to remove an element by the index, or keep a previous node to hold the value of the node that comes before current and when you remove, set previous.setNext(current.getNext()) which will effectively delete current.
Second, you've made use of the equals method for Object, which uses the most discriminating method for determining equality, in that it will only return true for cases where the two compared objects refer to the same object. While this isn't necessarily a problem this can lead to issues depending on the type of data you store. Calling equals on any object will default to the closest implementation of equals for the actual type of data being represented by that object, so if it can't find one, it will default to Objects implementation, which will almost always give a false result if the objects are not the same.
The equals method for class Object implements the most discriminating
possible equivalence relation on objects; that is, for any non-null
reference values x and y, this method returns true if and only if x
and y refer to the same object (x == y has the value true).
Barring that, you might want to change how you compare object data, but I don't think that will really cause you too much of an issue.
Lastly, you will probably want to do some null checking and work your looping algorithm a bit, since this one will have problems if the duplicates are at the head of the list, but this should get you pointed in the right direction.
Here's a cut at a method that can help shed some light on what I've said:
public void removeSecondAppear(Object data)
{
Node temp = new Node(data);
Node current = head;
Node previous = null;
boolean found = false;
while(current != null)
{
// for the sake of argument, let's say this will return true if you find equal data
if( current.getData() != null && current.getData().equals(temp.getData()))
{
if(found)
{
// remove element
previous.setNext(current.getNext());
listCount--;
break;
}
else
{
found = true;
}
}
else {
found = false;
}
previous = current;
current = current.getNext();
}
}
Edit: I've written a small subset of a LinkedList implementation using the OP's Node class definition and used a small test to make sure my removeSecondAppear method works.
public class LinkedList {
private Node head;
public LinkedList() {
head = new Node(0);
}
public LinkedList(Node node) {
head = node;
}
public void add(Node node) {
Node ptr = head;
while ( ptr.getNext() != null ) {
ptr = ptr.getNext();
}
ptr.setNext(node);
}
... /// added removeSecondAppear here, but left out to keep it short(er)
// provided a print() method
}
Using this test:
public class Test {
public static void main(String[] args) {
LinkedList list = new LinkedList(new Node(1));
list.add(new Node(2));
list.add(new Node(4));
list.add(new Node(4));
list.add(new Node(5));
list.print();
list.removeSecondAppearance(4);
list.print();
}
}
My output is:
1 2 4 4 5
1 2 4 5
Adding to pmac89's answer, it would be better if you genericized your node class so that you can use the proper .equals() method for the type of your data:
public class Node<T> {
Node<T> next;
T data;
...
}
From that point essentially you can replace Object with T and Node with Node<T>. When you create a node, you specify its type. Then, say you make a Node<String>. When you call .equals() on the data, it will use String.equals() instead of Object.equals().
The reason you don't want to call Object.equals() is, as pmac89 said, because you are checking if they are the same object. What you really want to check is whether they have the same value.
Edit:
As Ryan J mentioned, if your data is a subclass of Object, it will default to the equals() implementation for that type, if there is one.
Here's the generics tutorial if you aren't familiar with them:
http://docs.oracle.com/javase/tutorial/java/generics/
So the problem is your Node class....
In
public class Node {
...
Object data;
....
}
So when you are calling
if(current.getData().equals(temp.getData()))
in your removeSecondAppear, they will not equal. Remember, Object.equal() on an object is comparing memory locations. None of the list items will equal each other, only the item itself.
EDIT: Also you would want
previous.setNext(current.getNext()) //Oops, fixed a mistake here too!!!
EDIT 2:
Also you are not excluding the thing you are looking for, so you are finding itself. To elaborate on this, think of it this way;
I have the list 1, 2, 3, 4, 4, 5. How many times does it find 4? I am guessing once. The reason being is that each of the list items has an address that does not match the other, as this is saying data is an Object which is assigned a place in memory. So when you call the Object.equals(someOtherObject) you are asking if they have the same location in memory. They do not have the same location in memory. The reason why you are only finding 1 second appearance in your check during the removeSecondAppear is because you are going through the whole list again and not excluding the node that you are looking for.
I need to write a function to find previous/next leaf node that meet special condition from any node in a singly rooted tree. (in the parent first order)
The API would be something like this:
Node findNextLeafNode(Node currentNode, Condition condition);
Node findPretLeafNode(Node currentNode, Condition condition);
where currentNode is any node in a tree, and Node is defined as:
interface Node{
/** #return the Node's parent or null if Node is root */
Node getParent();
/** #return true if node is root */
boolean isRoot();
/** #return non-null array of child nodes (zero length for leaf nodes) */
Node[] getChildren();
/** #return the number of child nodes. If node is leaf, value is 0 */
int getChildCount();
}
And the Condition interface defines the semantics of checking a constraint against a given Node.
interface Condition{
/** #return true if provided node meets the condition */
boolean check(Node node);
}
My question:
Is there an existing library or algorithm for such a common scenario? I am open to either stack based or recursive algorithms. Pseudocode, links to open source libraries, or if you care to share you own code, would be appreciated.
(If not, I need to spend time to invent the same wheel again and paste it here later for sharing.)
Thanks.
-----------------------------write a method to getNext()........
// currentNode must be descendant of root
public static Node getNextNode(Node currentNode, Node root)
{
// 1. if is has child, next is its first child
if (currentNode.getChildSize() > 0) {
return currentNode.getChildren()[0];
}
// 2. if it has no child, check if its is the last child of his parent
else {
// if it is root and has no children, return null
if (currentNode == root) {
return null;
}
// else should have parent which is or under root;
Node parent = currentNode.getParent();
int index = getIndex(currentNode);
if (!isLastofParent(currentNode)) {
// ----a. if not last, next is his parent's next
return currentNode.getParent().getChildren()[index + 1];
}
else {
// ----b. if it is the last one, return its parent's next right if there is. while until root
Node tmp = parent;
while (tmp != root) {
int parentIndex = getIndex(tmp);
if (!isLastofParent(tmp)) {
return tmp.getParent().getChildren()[parentIndex + 1];
}
tmp = tmp.getParent();
}
}
}
return null;
}
private static boolean isLastofParent(Node node)
{
if (getIndex(node) == node.getParent().getChildSize() - 1) {
return true;
}
return false;
}
private static int getIndex(Node currentNode)
{
Node parent = currentNode.getParent();
for (int i = 0; i < parent.getChildSize(); i++) {
if (parent.getChildren()[i] == currentNode) {
return i;
}
}
//TODO: error condition handling, will not happen if tree not change
return -1;
}
------------------------a full search is much easier............
public static Node getNextFailNode(Node currentNode, Node root, Condition condition)
{
boolean foundCurrentNode = false;
Stack<Node> stack = new Stack<Node>();
stack.push(root);
while (!stack.isEmpty()) {
Node tmp = stack.pop();
System.out.println("-popup---------" +tmp+ " ");
if (foundCurrentNode && checkCondition(tmp, condition)) {
return tmp;
}
if (tmp == currentNode) {
foundCurrentNode = true;
}
if (tmp.getChildSize() > 0) {
for (int i = tmp.getChildSize() - 1; i >= 0; i--) {
stack.push(tmp.getChildren()[i]);
}
}
}
return null;
}
This maybe way overblown for what you need, but it can support what you want:
There is a graph traversal language: Gremlin. Typically bolted on top of something like Neo4j, but any graph data structure (e.g. a singly rooted directed tree) can be wrapped to support the API. Take a look at Blueprints projects to find out how it is done.
[edit: for something less heavy]
Perhaps JGraphT is what you want. Also take a look at this question on SO. It is not an exact duplicate, but you should find it helpful.
Write an iterator for your tree that can be initialized from any node and uses pre/in/post-order traversal (Of course it should be bi-directional).
This is basically writing one simple algorithm that at least to me seem basic.
Once you have an iterator all you need is to iterate your way to the next node which is a leaf and the condition holds for it.
If you have trouble with any specific part just ask and I'll improve my answer.
Based on the fact that you already have defined your interfaces, and you say the graph-traversal libraries are too heavyweight, you probably should just write it yourself. It would be an absolutely trivial amount of code. (This page contains some code if you need help.)
(One suggestion for your API: don't put a boolean isRoot(); method on Node, that's a waste of bits unless you have a very good reason to do so. The code that builds the tree should just refer to the root node.)
This is for homework but please know that I have looked online for help (such as http://www.sethi.org/classes/class_stuff/cis435/others/notes-java/data/collections/lists/simple-linked-list.html) and my textbook but I am still having some issues.
Any help would be appreciated...
Right now I'm trying to just insert values in but nothing is working. Whether it's the first item, whether it's being added as the last one, or somewhere in between.
Node header = null; // First element of list.
Node back = null; // Last element of list.
public void insert(int i, double value){ //insert value before i-th element
Node e = new Node();
e.num = value;
Node curr = header;
for(int x=0;x<i;x++) {
if (i == 1) { //we want to insert as first thing
if (size == 0) { //its the FIRST time we add something
header.next = e;
e.next = back;
break;
} else if (size == 1){
e.next = header.next; //i.e. the second thing in the list
header.next = e;
break;
} else {
e.next = header.next.next; //i.e. the second thing in the list
header.next = e;
break;
}
}
else if (x == (i-1)) {
e.next = curr.next;
curr.next = e;
break;
}
curr = curr.next;
}
size = size+1;
}
Not really sure why it isn't working.
Thanks!
For some reason, people who are still learning to program make things far more complicated then they need to be. I did it when I was learning java, I still do it when I am just getting into a new language, and students that I have marked find new and amazing ways to do it. You have more going on in your insert then there needs to be, for example, a method that inserts a value at a specific index should not check if it's the first item to be inserted (not saying it shouldn't check bounds). Here is the pseudo code of what I would do.
insert(index, value)
if index>size
throw null pointer
traverse to index -1 //lets call this nodeI
create newnode and set value
set newnode.next to nodeI.next
set nodeI.next to newnode
increase size.
Couple of handy hints for you, you should have a function to get an element from the link list, something that returns a node? public node elementAt(int index) for example? use that to traverse the linked list. If you want to append to the Linked list, try this
append(value)
insert(size-1,value)
and if you want to insert at the beginning? same idea
insert(value)
insert(0,value)
In the line e.next = header.next.next what would happen if header.next points to a 'null'? Is it possible to get there?
What are the corner cases you have to deal with and have you taken them all into account?
Can you start with the simplest case first, adding either an element to the front or an element to the back? Then use those functions to implement the insert?
A few suggestions:
implement java.util.List
Think about generics
Read this.
Start with "insert at the end" before you think about "insert at i".
I have tried a simple program, which will be useful for you guys, I am also learning Java, please bear with me for any mistakes, but this program works fine.
I am posting a very simple singly linked list program in Java, which I tried out today.
I hope it will help all.
LinkList.java
class LinkList
{
public static void main(String args[])
{
Node node = new Node(1);
node.addAtLast(2);
node.addAtLast(3);
node.addAtLast(4);
node.addAtLast(5);
node.printList();
}
}
Node.java
class Node
{
private int data;
private Node link;
public Node(int mydata)
{
data = mydata;
link = null;
}
public void printList()
{
System.out.print("|"+data+"|"+"->");
if(link != null)
{
//recursive call
link.printList();
}
else
{
//marking end of list as NULL
System.out.print("|NULL|");
}
}
public void addAtLast(int mydata)
{
if(link == null)
{
link = new Node(mydata);
}
else
{
link.addAtLast(mydata);
}
}
}
OUTPUT :
The below is our output
|1|->|2|->|3|->|4|->|5|->|NULL|