Given input (items = 6, position = 3)
creates a row of 6 items and a character positioned on item 3 {0,1,2,[3],4,5}
A call to left() moves the character two positions to the left and the item at position 3 is removed {0,[1],2,4,5}
The next call to right() moves the character two positions to the right and the item at position 1 is removed {0,2,[4],5}
Then calling position() method now should return 4.
The character will not move to the left or right if no items are present so no need to implement that.
public class MyClass {
int position;
int[] items;
public MyClass(int n, int position) {
this.position = position;
items = new int[n];
for(int i=0; i<n; i++) {
items[i] = i;
}
}
}
public void left() {
int p = this.position;
items[p] = -1;
for(int z=0; z<2;) {
p--;
int value = arr[p];
if(value != -1) {
z++;
}
}
this.position = p;
}
public void right() {
int p = this.position;
items[p] = -1;
for(int z=0; z<2;) {
p++;
int value = arr[p];
if(value != -1) {
z++;
}
}
this.position = p;
}
public int position() {
return arr[position];
}
This code works perfectly for small inputs, but I am getting performance errors when the input is large.
How to implement this efficiently? I don't have test case details for the error related to performance errors.
As it already has been pointed outed both in the comments and the answer by #AbhinavMathur, in order to improve performance you need to implement Doubly linked list data structure.
Note that it's mandatory to create your own implementation that will maintain a reference to the current node. Attempt to utilize an implementation built-in in the JDK in place of the items array will not buy you anything because the advantage of the fast deletion will be nullified by the cost of iteration (in order to reach the element at position n, LinkedList needs to crawl through the n elements starting from the head, and this operation has a liner time complexity).
Methods left(), right() and position() will have the following outcome:
left() - in case when the previous node (denoted as prev in the code) associated with current is not null, and in tern its previous node exists, the current node will be dereferenced (i.e. next and previous nodes associated with the current node will be linked with each other), and the variable current would be assigned to the prev of the previous node, i.e. current.prev.prev. Time complexity O(1).
right() - in case when the next node (denoted as next in the code) associated with current is not null, and in tern its next node exists, the current node will be dereferenced in a way that has been described above, and the variable current would be assigned to the next of the next node, i.e. current.next.next. Time complexity O(1).
position() - will return a value of the current node. Time complexity O(1).
That's how it might look like:
public class MyClass {
private Node current; // a replacement for both position and items fields
public MyClass(int n, int position) {
Node current = new Node(0, null, null); // initialing the head node
if (position == 0) {
this.current = current;
}
for (int i = 1; i < n; i++) { // initialing the rest past of the linked list
Node nextNode = new Node(i, current, null);
current.setNext(nextNode);
current = nextNode;
if (position == i) {
this.current = current;
}
}
}
public void left() { // removes the current node and sets the current to the node 2 position to the left (`prev` of the `prev` node)
if (current.prev == null || current.prev.prev == null) {
return;
}
Node prev = current.prev;
Node next = current.next;
prev.setNext(next);
next.setPrev(prev);
this.current = prev.prev;
}
public void right() { // removes the current node and sets the current to the node 2 position to the right (`next` of the `next` node)
if (current.next == null || current.next.next == null) {
return;
}
Node prev = current.prev;
Node next = current.next;
prev.setNext(next);
next.setPrev(prev);
this.current = next.next;
}
public int position() {
return current.getValue();
}
public static class Node {
private int value;
private Node prev;
private Node next;
public Node(int value, Node prev, Node next) {
this.value = value;
this.prev = prev;
this.next = next;
}
// getters and setters
}
}
A link to Online Demo
Using an array, you're setting the "removed" elements as -1; repeatedly skipping them in each traversal causes the performance penalty.
Instead of an array, use a doubly linked list. Each removal can be easily done in O(1) time, and each left/right operation would only require shifting the current pointer by 2 nodes.
Related
How would I do a time complexity analysis for my get() method?
private DNode find(int index)
{
DNode curr = head; // alias
// Conditional Statements - if the index is in the first half of the list, loop forward to find
if(index >= 0 && index <= size()/2)
{
// For loop - indexes the reference result to the next node
for(int skip = 0; skip < index; skip++)
{
curr = curr.getNext();
}
}
// Otherwise, loop backwards in the list
else
{
// For loop - indexes the reference result to the back node
for(int skip = 0; skip < index; skip--)
{
curr = curr.getBack();
}
}
return curr; // The item at the specified index for the node
}
public Object get(int index) throws ListIndexOutOfBoundsException
{
// Conditional Statements - checks if index is valid
if(isValid(index))
{
DNode result = find(index);
return result.getItem();
}
throw new ListIndexOutOfBoundsException("Out of bounds");
}
How do I test for the best, worst, and average cases for time complexity? I'm a little confused on how I analyze for this.
EDIT: I've added my find() method
I was trying to sum the value of BST's nodes with exactly one child.
however, for some reason, it didn't going through.
For example, the input{1,2,3,4,5,6,7,8,9,10} and the output of it should be 45. I only got 2.
and for {5, 2, 1, 7, 6, 8, 10}, i got 0. I'm in the BST tree. Could anyone explain it and fix my code?
public class Node {
Integer value;
Node parent;
Node left;
Node right;
public Node(Integer value) {
this.value = value;
this.parent = null;
this.left = null;
this.right = null;
}
}
public Integer oddNodeSum() {
return oddNodeSum(root) ;
}
private Integer oddNodeSum(Node root) {
// START YOUR CODE
int index=0;
if (root==null){
return index+=0;
}
else {
if (root.left!=null&&root.right==null){
index += root.left.value;
oddNodeSum(root.left);
}
if (root.left==null&&root.right!=null){
index += root.right.value;
oddNodeSum(root.right);
}
return index;
}
}
the problem on your code is you are traversing node only when the condition of adding node (with one child) are satisfying. instead of it, you need to traverse all the child and you need to consider those node whose having only one child.
i modified your code like following:
private int oddNodeSum(Node root) {
int sum = 0;
if(root == null) {
return 0;
}
/* node with only one child */
if((root.left == null && root.right != null) || (root.left != null && root.right == null)){
sum += root.val;
}
/* traverse all node and add whose having only one child */
sum += oddNodeSum(root.left);
sum += oddNodeSum(root.right);
return sum;
}
Initialise the index = 0 in oddNodeSum() function, before the oddNodeSum(root) is called and pass the index into the `oddNodeSum(root, index) and try to implement the logic over there. This will rectify your issue
I am totally stuck on this problem. I need to output the position of a value in an inorder list (First index 0). The caveat is that I can't create the list and search through it. For each node I have a variable that contains information about how many nodes are in any given tree (including the root). I have it working for about 50% of the cases but the rest fail in hard to understand ways... If the value doesn't exist i need to return the index where it would have been.
In the class Tree
public int position(int val) {
if (this.isEmpty()){
return 0;
}
if (val == root.key){
return (root.subNodes - root.rightchild.subNodes) - 1;
}
if (val < root.key){
return root.position(0,root.subNodes - 1,val,root);
} else {
return (root.subNodes - root.rightchild.subNodes) +root.position(0,root.subNodes - 1,val,root.rightchild);
}
}
In the class node
int position(int min, int max, int k, Node n){
if (k == n.key){
if (n.rightchild != null){
return n.subNodes - (n.rightchild.subNodes);
}
return max;
}
if (n.rightchild == null && n.leftchild == null){
return 1;
}
if (k < n.key){
return position(min ,n.leftchild.subNodes - 1, k, n.leftchild);
}
if (k > n.key && n.rightchild != null){
return position(n.subNodes - (n.rightchild.subNodes + 1), n.subNodes - 1, k, n.rightchild);
}
return max;
}
The Idea:
You can do an in order traversal of the tree and keep track of the number of nodes you have visited. This requires a counter of some sort and probably a helper method.
We stop searching when we find a node with a value greater than or equal to the desired value. This is because we either found the index of the desired value or the index of where the desired value would go (the desired value wouldn't go in any earlier or later indexes). If we never find a node equal or greater than desired value, then the desired value would go at the end of the tree, which has a position equal to the count of nodes.
The Implementation:
Imagine you have this Node
public class Node {
int value;
Node leftChild;
Node rightChild;
// Getters and Setters
}
And this Tree
public class Tree {
Node root;
// Getters and Setters
}
Inside of Tree
public int position(int val) {
positionHelper(val, root, 0);
}
public int positionHelper(int val, Node currentNode, int steps) {
// In-order search checks left node, then current node, then right node
if(currentNode.getLeftChild() != null) {
steps = positionHelper(val, currentNode.getLeftChild(), steps++);
}
// We found the node or have already moved over the node, return current steps
if(currentNode.getValue() >= val) {
return steps;
}
// Next Node Index
steps++;
if(currentNode.getRightChild() != null) {
steps = positionHelper(val, currentNode.getRightChild(), steps++);
}
return steps;
}
Let me know if it has any issues or there are any questions
I have a binary search tree where i have to implement a method called
int valueAtPosition(int x)
The problem is, that i need the position in an in order traversal.
To find the in order traversal i have this the following code, but i don't know how i count the recursive calls, to get the right position.
public void inOrderTraverseTree(Node root){
if(root != null){
inOrderTraverseTree(root.leftChild);
System.out.println(root);
inOrderTraverseTree(root.rightChild);
}
}
I think the other solutions are O(n). All you need for this is a count of the children for each node for O(log n).
When you insert a node, for each node you traverse you increase the counter on the traversed node by one.
You need to maintain these counters when deleting, rebalancing, etc which normally isn't difficult.
With this you can get the position of the node when inserted, find the position of a node by value or find a node by position.
To find a node by position is the same kind of binary traversal as for finding by value. If you want the item at position 1000 then you start at the root. No root, not item at that position. Then you look at the left child (you can do it in the other order too and switch ascending/descending), on the left if the left child exists the number of children on the left is 0 plus the count of the children on the left node. Let say in this scenario that the left exists and has 500 children. Then you know 1000 can't be left because there aren't enough items on the left, so it must be right. You can repeat this also checking for bounds all the way down.
For simple O(n) in order traversal if you have a global counter you just increase it only after traversing the left. That should do the same as a depth first search. No need for decreasing and increasing counters or pushing and popping on a stack. You can also have your functions return a count.
public int inOrderTraverseTree(Node root){
if(root == null)
return 0;
int count = inOrderTraverseTree(root.leftChild);
count++;
count += inOrderTraverseTree(root.rightChild);
return count;
}
This approach only becomes annoying if you want to return the node as well.
You can of course replace a recursive function with your own stack but this is a rarely needed performance optimisation and you'll be far better off with the O(log n) solution if you need performance than an optimised custom stack based solution.
You can also use a counter in the recursive approach. However, you can't simply pass an int counter argument - you need all calls to see the "same" counter, so you will have to wrap it in a class (or, as in this case, an inner class):
public static class Counter {
private int value;
public Counter(int initialValue) { value = initialValue; }
public boolean decrement() { value--; return value == 0; }
public boolean expired() { return value <= 0; }
}
public Node inOrderTraverseTree(Node root, Counter counter){
if (root != null && ! counter.expired()) {
Node left = inOrderTraverseTree(root.leftChild, counter);
if (left != null) {
return left;
} else if (counter.decrement()) {
return root;
} else {
return inOrderTraverseTree(root.rightChild, counter);
}
} else {
return null;
}
}
To find the 9th node in-order (using 1-based indexing), you would call this as
Node the9th = inOrderTraverseTree(root, new Counter(9));
If there is no 9th node, it would return null. If you want to use 0-based indexing instead, change { value--; return value == 0; } to { return value-- == 0; }
The iterative in-order traversal approach makes this pretty easy. Increment a counter whenever a node is popped from the stack. When the counter is equal to x, return the value of the node.
Integer valueAtPosition(int x, Node root) {
int count = 0;
List<Node> stack = new ArrayList<>();
Node node = root;
while (!stack.isEmpty() || node != null) {
if (node != null) {
stack.add(node);
node = node.leftChild;
} else {
node = stack.pop();
if (count == x) {
return node.value;
}
count++;
node = node.rightChild;
}
}
return null;
}
Recursive version requires passing a mutable wrapper for a counter like so:
public class Counter {
int count = 0;
}
public void inOrderTraverseTree(Node root, int index, Counter counter){
if(root == null || counter.count > index) {
return;
}
inOrderTraverseTree(root.leftChild);
if (counter.count == index) {
System.out.println(root);
}
counter.count = counter.count + 1;
inOrderTraverseTree(root.rightChild);
}
Following is recursive in-order traversal approach: (in c++)
bool valueAtPositionUtil(struct treeNode *root, int &currIndex, int i, int &value) {
if(root != NULL) {
if(valueAtPositionUtil(root->left, currIndex, i, value)) {
return true;
}
if(currIndex == i) {
value = root->data;
return true;
}
currIndex++;
if(valueAtPositionUtil(root->right, currIndex, i, value)) {
return true;
}
}
return false;
}
int ValueAtPosition(int i, struct treeNode *root) {
int value = 0;
int currIndex = 0;
if(valueAtPositionUtil(root, currIndex, i, value)) {
return value;
}
//index out of bound
// you can return according your problem
return -1;
}
So I have a homework question where I'm supposed to use a recursive method to "find the minimum element within a subtree rooted at the specified node"
And then I'm given this as my starting point:
public TreeNode
{
int data;
TreeNode left;
TreeNode right;
}
and
/**
Finds the minimum value for the subtree that is
rooted at a given node
#param n The root of the subtree
#return The minimum value
PRECONDITION: n is not null.
*/
int min(TreeNode n)
{
// COMPLETE THE BODY OF THIS METHOD
}
Now, I've got a very basic driver program written to insert nodes into the tree and I've written my recursive method, but it seems to be counting up instead of down, here's my method:
int min(TreeNode n){
if(n.left != null) {
n = n.left;
min(n);
System.out.println("N is now " + n.value);
}
return n.value;
}
Output of my code:
Building tree with rootvalue 25
=================================
Inserted 11 to left of node 25
Inserted 15 to right of node 11
Inserted 16 to right of node 15
Inserted 23 to right of node 16
Inserted 79 to right of node 25
Inserted 5 to left of node 11
Inserted 4 to left of node 5
Inserted 2 to left of node 4
Root is 25
N is now 2
N is now 4
N is now 5
N is now 11
The minimum integer in the given nodes subtree is: 11
Can someone please explain to me why this doesn't work?
Note: this is all assuming you're in a Binary Search Tree, so returning the minimum element means returning the left-most element.
This means your recursive call is quite simple:
min(node):
if this node has a left node:
return min(node.left)
if this node does not have a left node:
return this node's value
The logic is that if we don't have another left node then we are the left-most node, so we are the minimum value.
Now, in Java:
int min(TreeNode n){
if (n.left == null)
return n.value;
return min(n.left); // n.left cannot be null here
}
Now to explain your results, consider how this method works. It calls the method on the next node (min(n.left)) before continuing. In your case you had a println after this recursive call. Therefore the println inside the recursive call went first. So your prints started at the bottom of the tree and worked their way back up. This explains the "reverse order" printing.
Your method then returned 11 as your result because (as another answer has explained) your n = n.left didn't affect any of your recursive sub-calls, only the one in the current function call. This means you returned the left node of the root, rather than the furthest left child.
I hope this makes sense. If you need clarification on anything leave a comment or something. Recursion can be quite tricky to get your head around at first.
The issue is that Java is call-by-value, not by reference -- although references are passed by value. But what that really means in this case is that the call to min(n) does not change what the variable n refers to -- it doesn't do anything at all. What you should probably be doing is return min(n).
public static void main(String[] args) throws IOException, NoSuchMethodException, InitializationError {
Logger.getRootLogger().addAppender(new ConsoleAppender(new SimpleLayout(), "System.out"));
Logger.getRootLogger().setLevel(Level.ALL);
TreeNode n1 = new TreeNode();
TreeNode n2 = new TreeNode();
TreeNode n3 = new TreeNode();
TreeNode n4 = new TreeNode();
TreeNode n5 = new TreeNode();
TreeNode n6 = new TreeNode();
n1.data = 110;
n1.left = n2;
n1.right = n3;
n2.data = 15;
n2.left = n4;
n2.right = null;
n3.data = 3;
n3.left = null;
n3.right = null;
n4.data = 4;
n4.left = null;
n4.right = n5;
n5.data = 12;
n5.left = n6;
n5.right = null;
n6.data = 19;
n6.left = null;
n6.right = null;
System.out.print("min=" + min(n1));
}
static public class TreeNode {
int data;
TreeNode left;
TreeNode right;
}
static int min(TreeNode n) {
return min(n, n.data);
}
static int min(TreeNode n, int min) {
System.out.println("N is now " + n.data);
int currentMin = min;
if (n.left != null && n.right != null) {
final int left = min(n.left);
final int right = min(n.right);
if (left < right) {
currentMin = left;
} else {
currentMin = right;
}
} else if (n.left != null) {
currentMin = min(n.left);
} else if (n.right != null) {
currentMin = min(n.right);
}
if (currentMin < min) {
return currentMin;
} else {
return min;
}
}
OUTPUT is:
N is now 110
N is now 15
N is now 4
N is now 12
N is now 19
N is now 3
min=3
You need to use some tree traversal algoritm, for checking every node of the tree. Also you need to store current finded minimum. Pass this minimum into recursive function. It is calling "accumulator".
The last statement in your method implementation returns the node n's value. As n starts with the root and is replaced by its left child (if exists) you always get the value of the root's left child.
The following code should do it:
int min(final Tree n){
int result;
if(n == null){
result = Integer.MAX_VALUE;
} else {
result = n.value;
final int leftResult = min(n.left);
if(leftResult < result){
result = leftResult;
}
final int rightResult = min(n.right);
if(rightResult < result){
result = rightResult;
}
}
return result;
}
Or you could use the Visitor pattern (you would need to make your tree Iterable then and pass the values to the Visitor one-by-one):
interface TreeVisitor {
void accept(int value);
}
class MinTreeVisistor implements TreeVisitor {
int min = Integer.MAX_VALUE;
#Override
public void accept(int value) {
if(value < this.min) {
this.min = value;
}
}
}