I need to create a method in java that recursively determines the distance from any given node back to the root. The method returns an integer that shows how many nodes away the specific node is from the root. The node class is given below
Public class Node
{
int data;
node left;
node right;
}
No global variables or attributes allowed, and I cannot modify the node class. I've looked it up and each solution tells me to modify the node class to include a node pointer for a parent node. Any help would be appreciated, thanks!
If you have parent stored in each node, search would require O(log N) operations (in case of balanced tree)--you just walk through parents and count steps until parent == null which means root node.
But without parent field, you need to recursively traverse the whole tree starting from the root, looking for a given node. It requires O(N) operations:
/** Returns the distance between "n" and "current" plus "step"
/* or -1 if "n" not found */
int distance(Node n, Node current, int step) {
int res = -1;
if (n == current) // node found
return step;
if (current.left == null && current.right == null) // leaf node
return -1;
if (current.left != null) // search in left subtree
res = distance(n, current.left, step + 1);
if (res > 0)
return res;
if (current.right != null) // search in right subtree
res = distance(n, current.right, step + 1);
return res;
}
//....
Node root;
Node given;
int dist = distance(given, root, 0); // distance between "root" and "given"
Related
I have the following working code to find the LCA for a Binary Tree (not BST) recursively on O(n) time and since I use recursion, in O(n) space.
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
public class LCA {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null) return null;
if(p == root || q == root) return root;
TreeNode L = lowestCommonAncestor(root.left, p, q);
TreeNode R = lowestCommonAncestor(root.right, p, q);
// Check 1
// if one of p or q is in left subtree and other is in right subtree
// then root is the LCA.
if(L != null && R != null) return root;
// Check 2
// else if L is not null, L is LCA. because p and q both are in left subtree
// else, LCA is in R as p and q are in right subtree
return L != null ? L : R;
}
}
However, I need to do this iteratively in O(n) time and O(1) space.
I have the following code but it uses list to save the two paths that makes it O(n) time and O(n) space
public class LCA {
List<List<TreeNode>> bothPaths = new ArrayList<List<TreeNode>>();
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(p == root || q == root) return root;
findPaths(root, new ArrayList<TreeNode>(), p);
findPaths(root, new ArrayList<TreeNode>(), q);
List<TreeNode> listP = bothPaths.get(0);
List<TreeNode> listQ = bothPaths.get(1);
int len = Math.min(listP.size(), listQ.size());
TreeNode previous = null;
for(int i=0; i<len; i++){
if(listP.get(i) == listQ.get(i)){
previous = listP.get(i);
}
else{
break;
}
}
return previous; // common element between 2 list
}
private void findPaths(TreeNode root, ArrayList<TreeNode> tempList, TreeNode temp){
if(root == null) return;
tempList.add(root);
if(root == temp){
bothPaths.add(tempList);
return;
}
findPaths(root.left, new ArrayList<TreeNode>(tempList),temp);
findPaths(root.right, new ArrayList<TreeNode>(tempList), temp);
}
}
I want to know if any O(n) time and O(1) space ITERATIVE algorithm exists to do this?
Go up from p unless you reach a top. This will give you depth_p of p node. Do the same to get depth_p. Then you will have depth_p and depth_q. Let l be lowest of p and q and h be highest of them. Go up from l to |depth_p - depth_q| levels. This new node together with h will give you two nodes of the same level. Go up together from from these two nodes and they will meet at the common parent.
PS: if you don't have parent pointer, then you can play with sending iterators of speed 1 and 1/2 from left and right side. One of this iterators will reach another in some common node, you can use it later as root node.
Assuming you have parent pointers, go up from p and q to the root to compute their depth in the tree, say m and n. Then, go up from p and q to the root in lockstep, one level at a time, until the node is the same for both searches, but first go up |m-n| levels in the tree for whichever of p and q are further from the root.
How would I go about setting an index for each node after generating a binary tree?
(a) (1)
(x) (r) => (2) (3)
(o)(t)(t)(x) (4)(5)(6)(7)
So I can then use a call such as getIndex()at a particular node to return its index.
My tree class:
public class BT<E>{
E value;
BT<E> left, right;
int Index;
public BT(E value)
{
this.value=value;
}
public BT (E value, BT left, BT right)
{
this.value = value;
this.left = left;
this.right = right;
}
Breadth-first traversal.
Queue<BT> queue = new LinkedList<BT>() ;
public void breadth(BT root) {
if (root == null)
return;
queue.clear();
queue.add(root);
int index = 0;
while(!queue.isEmpty()){
BT node = queue.remove();
node.Index = index;
index++;
if(node.left != null) queue.add(node.left);
if(node.right != null) queue.add(node.right);
}
}
Adapted from here.
If you are doing this after the tree is fully created, then something that uses level-order traversal will work. It's not terribly efficient, but it's straight-forward recursion:
/* Method to set index based on level-order traversal of tree */
public void initIndices(BT root) {
int maxIndexSoFar = 0;
for (int d = 1; d <= root.height(); ++d)
maxIndexSoFar = setIndexAtLevel(root, d, maxIndexSoFar);
}
/* Method to set index of all nodes at a given level */
private int setIndexAtLevel(BT node, int level, int index) {
if (tree == null)
return index;
if (level == 1) {
index++;
node.setIndex(index);
return index;
}
else if (level > 1) {
int newIndex = setIndexAtLevel(node.left, level-1, index);
newIndex = setIndexAtLevel(node.right, level-1, newIndex);
return newIndex;
}
return -1;
}
I'll leave you to create the height() method and setIndex() methods. Fair warning, I have not tested this at all, so pardon any typos.
So you are to implement a procedure getIndex(int index) which has to return you the node with that index?
If so, you are looking for an efficient way to represent a binary tree.
You could traverse the tree for each call to getIndex but this wouldn't be efficient...
An efficient solution is to store the complete binary tree in an array, because of the O(1) access it provides. Store a node n at index n in the array and its child nodes at index 2*n and (2*n) - 1. But here the restrictions are that the tree has to be complete and the size of an array is not variable (if the binary tree becomes too big, a bigger array (usually twice as big) should be made and all elements should be copied).
This is a handy solution because :
Node access is in O(1) but a procedure like addNode() would become amortized in O(1). (*)
A node does not have to remember it's child nodes --> this.left becomes this.left() with the implementation of left() provided below.
A possible implementation for left() procedure.
static int[] binaryTreeArray = new int[maxTreeSize]; // BT of integers for example
...
public int left() { // returns integer or ... (type of your nodes)
return binaryTreeArray[(this.Index)*2]; // O(1)
}
(*) An addNode()-like procedure would add nodes in O(1) (binaryTreeArray[index] = nodeValue;) most of the time but when the binaryTreeArray is full it will have to make a bigger array that is usually twice as big (O(n) for the copying). It can be shown that this has an amortized cost of O(1) but this has no added value for this answer.
So in a given binary tree (node binary search tree), initially I want to find the number of nodes between two nodes "p" and "q". I first find the lowest common ancestor between these two nodes, say, "ancestor". Then I calculate the number of nodes between "ancestor" and "p" and number of nodes between "ancestor" and "q" separately and add them at last.
I tried recursive way to get number of nodes between "ancestor" and "p" or "q" but failed. Not a fan of recursive.
public static int NodeToNodePath(BinaryTree root, BinaryTree node, int length){
if(root == null && node == null)
return 0;
if(root == null || node == null)
return 0;
if(root.rootElement == node.rootElement){
return length;
}
int sum = NodeToNodePath(root.left, node, length + 1);
if(sum != 0)
return sum;
sum = NodeToNodePath(root.right, node, sum);
return sum;
}
But in this way, the result from root to left mode is correct but can't find node on the other size.
Any help?
Thanks!
I figure out how to solve the problem. By recursion. This may not apply to my origin problem
"find node number between two given nodes" but it does return number of nodes between root and a given node.
Code is posted below.
public static int NodeToNodePath(BinaryTree root,
BinaryTree node, int length) {
if(root == null)
return 0;
if(root.rootElement == node.rootElement){
length += 1;
return length;
}
int left = NodeToNodePath(root.left, node, length);
if(left != 0){
return left + 1;
}
int right = NodeToNodePath(root.right, node, length);
if(right != 0){
return right + 1;
}
return 0;
}
Also, I found a post on GeekForGeeks talking specifically about my origin problem, it's called "Find distance between two given keys of a Binary Tree" the address is:
http://www.geeksforgeeks.org/find-distance-two-given-nodes/
Thanks everyone!
Completed my hw and I got it wrong. I do not understand why.
For my insert front I do the following.
head.next.prev = newNode;
newNode.next = head;
newNode.prev = null;
head.prev = newnode;
head.next.prev = head;
size++;
But instead the solution looks like this following
head.next.prev = newNode(item, head, head.next); // newNode(item,prev,next); So basically head.next.prev is pointing to a newnode here newnode.prev = head and newnode.next = head.next. Ok that make sense.
head.next = head.next.prev; // huh?
size++;
to me the solution doesn't make sense and my solution is perfectly logical. If you make head.next.prev = a new node, you should make head.next.prev = head, or else there will be a jump right? Also head.next = head.next.prev; doesn't make any sense. That line is basically saying head.prev is pointing to the head itself. Shouldn't it be head.next.prev = head;?
Can anyone point out what's going on? i know the format between the solutions is different but i'm more interested in the logic
The complete code is shown below
There's a lot of confusion. So here's how head is declared
public class DList {
/**
* head references the sentinel node.
* size is the number of items in the list. (The sentinel node does not
* store an item.)
*
* DO NOT CHANGE THE FOLLOWING FIELD DECLARATIONS.
*/
protected DListNode head;
protected int size;
/* DList invariants:
* 1) head != null.
* 2) For any DListNode x in a DList, x.next != null.
* 3) For any DListNode x in a DList, x.prev != null.
* 4) For any DListNode x in a DList, if x.next == y, then y.prev == x.
* 5) For any DListNode x in a DList, if x.prev == y, then y.next == x.
* 6) size is the number of DListNodes, NOT COUNTING the sentinel,
* that can be accessed from the sentinel (head) by a sequence of
* "next" references.
*/
/**
* newNode() calls the DListNode constructor. Use this class to allocate
* new DListNodes rather than calling the DListNode constructor directly.
* That way, only this method needs to be overridden if a subclass of DList
* wants to use a different kind of node.
* #param item the item to store in the node.
* #param prev the node previous to this node.
* #param next the node following this node.
*/
protected DListNode newNode(Object item, DListNode prev, DListNode next) {
return new DListNode(item, prev, next);
}
/**
* DList() constructor for an empty DList.
*/
public DList() {
head = newNode(null, head, head);
head.next = head;
head.prev = head;
size = 0;
}
public insertfront(Object item){
???????????}
//////////////////// below is the DlistNoe.java
public class DListNode {
/**
* item references the item stored in the current node.
* prev references the previous node in the DList.
* next references the next node in the DList.
*
* DO NOT CHANGE THE FOLLOWING FIELD DECLARATIONS.
*/
public Object item;
protected DListNode prev;
protected DListNode next;
/**
* DListNode() constructor.
* #param i the item to store in the node.
* #param p the node previous to this node.
* #param n the node following this node.
*/
DListNode(Object i, DListNode p, DListNode n) {
item = i;
prev = p;
next = n;
}
}
There's a lot wrong with your insertion code. Just read it in English:
head.next.prev = newNode;
Point the first node's "prev" to the new node (ok)
newNode.next = head;
Point the new node's "next" to the head (what?)
newNode.prev = null;
Point the new node's "prev" to null (it's the first node, so it should point to head)
head.prev = newnode;
Point the head's "prev" to null (you're inserting at the front so you shouldn't be touching this)
head.next.prev = head;
Point the first node's prev to head (undoing what you did in the first step)
So now you have a head that's still pointing to the old first element, and is not pointing back to the last element of the list anymore. And a new element that is not fully inserted (its "prev" is not pointing at anything, and its "next" is pointing at the wrong element).
Yeah, not really correct, I'd say. If you read the correct solution like the above, hopefully you'll see it makes more sense.
The trouble with structures like linked lists is that when you start modifying references, you lose which nodes are which.
So, let's name some nodes.
The linked list before insertion:
H -> A -> B -> C
H.next = A
H.prev = null
A.next = B
A.prev = H
And so on...
The Goal linked list:
H -> N -> A -> B -> C
H.next = N
H.prev = null (unchanged)
A.next = B (unchanged)
A.prev = N
N.next = A
N.prev = H
Based on the DList invariants and the given solution, there is a head node that does not hold a value that stays the head.
Then let's step through your code:
head.next.prev = newNode; // H.next -> A, A.prev = N. This seems fine.
newNode.next = head; // N.next = H. What? This doesn't match our goal.
newNode.prev = null; // N.prev = null. Also doesn't match our goal.
head.prev = newnode; // H.prev = n. Also doesn't match our goal.
head.next.prev = head; // H.next -> A, looks like you mean this to be N, but its still A.
// thus A.prev = H. Also doesn't match our goal.
size++;
Finally, let's look at the given solution.
head.next.prev = newNode(item, head, head.next);
// First the function, H.next -> A, so...
// N.prev = H. Matches goal.
// N.next = A. Also matches goal.
// Then the assignment:
// head.next -> A, A.prev = N. Matches goal.
head.next = head.next.prev;
// head.next -> A, A.prev -> N, H.next = N. Matches goal.
size++;
And thus, all 4 changed references have been set.
Consider:
Node reverse(Node head) {
Node previous = null;
Node current = head;
Node forward;
while (current != null) {
forward = current.next;
current.next = previous;
previous = current;
current = forward;
}
return previous;
}
How exactly is it reversing the list?
I get that it first sets the second node to forward. Then it says current.next is equal to a null node previous. Then it says previous is now current. Lastly current becomes forward?
I can't seem to grasp this and how it's reversing. Can someone please explain how this works?
You reverse the list iteratively and always have the list in the interval [head, previous] correctly reversed (so current is the first node that has its link not set correctly). On each step you do the following:
You remember the next node of current so that you can continue from it
You set the link of current to be pointing to previous, which is the correct direction if you think about it
You change previous to be current, because now current also has its link set correctly
You change the first node that does not have its link set correctly to be the one remembered in the first step
If you do that for all the nodes, you can prove (with induction for instance) that the list will be correctly reversed.
The code simply walks the list and inverts the links until it reaches the previous tail, which it returns as the new head.
Before:
Node 1 (Head) -> Node 2 -> Node 3 -> Node 4 (Tail) -> null
After:
null <- Node 1 (Tail) <- Node 2 <- Node 3 <- Node 4 (Head)
The easiest way to think about it is to think like this:
First add the head of the list to a new linked list.
Keep iterating through the original and keep adding the nodes before the head of the new linked list.
Diagram:
Initially:
Original List -> 1 2 3 4 5
New List -> null
1st Iteration
Original List -> 1 2 3 4 5
New List -> 1->null [head shifted to left, now newHead contains 1 and points to null]
2nd Iteration
Original List -> 1 2 3 4 5
New List -> 2-> 1->null [head shifted to left, now newHead contains 2 and points to next node which is 1]
3rd Iteration
Original List -> 1 2 3 4 5
New List ->3 -> 2-> 1->null [head shifted to left, now newHead contains 2 and points to next node which is 1]
Now it keeps looping through till the end. So finally the new list becomes:
New List-> 5 -> 4 -> 3 -> 2 -> 1 -> null
The code for the same should be like this (made it easy to understand):
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public ListNode reverseList(ListNode head) {
if(head == null) {
return null;
}
if(head.next == null) {
return head;
}
ListNode current = head;
ListNode previous = new ListNode(head.val);
previous.next = null;
while(current.next != null) {
current = current.next;
previous = addBeforeHead(current, previous);
}
return previous;
}
private ListNode addBeforeHead(ListNode node, ListNode head) {
if (node == null) return null;
ListNode temp = new ListNode(node.val);
temp.next = head;
head = temp;
return head;
}
public Node getLastNode()
{
if(next != null)
return next.getLastNode();
else
return this;
}
public Node reverse(Node source)
{
Node reversed = source.getLastNode();
Node cursor = source;
while(cursor != reversed)
{
reversed.addNodeAfter(cursor.getInfo());
cursor = cursor.getNodeAfter();
}
source = reversed;
return source;
}
I call it "cherry picking". The idea is to minimize the number of swaps. Swapping happens between a near and far index. It's a twp-pass algorithm.
(Odd length) A -> B -> C -> D -> E
(Even length) A -> B -> C -> D
Pre-Condition: N >= 2
Pass 1: Count N, the number of elements
Pass 2:
for(j=0 -> j<= (N/2 -1))
{
swap(j, (N-1)-j)
}
Example 1:
For above Odd length list, N = 5 and there will be two swaps
when j=0, swap(0, 4) // Post swap state: E B C D A
when j=1, swap(1, 3) // Post swap state: E D C B A
The mid point for odd length lists remains intact.
Example 2:
For above Even length list, N = 4 and there will be two swaps
when j=0, swap(0, 3) // Post swap state: D B C A
when j=1, swap(1, 2) // Post swap state: D C B A
Swapping applies to data only, not to pointers, and there might be any sanity checks missed, but you got the idea.
list_t *reverse(list_t *a)
{
list_t *progress = NULL;
while(a)
{
list_t *b; //b is only a temporary variable (don't bother focusing on it)
b = a->next;
a->next = progress; // Because a->next is assigned to another value,
// we must first save a->next to a different
// variable (to be able to use it later)
progress = a; // progress is initially NULL (so a->next = NULL
// (because it is the new last element in the list))
a = b; // We set a to b (the value we saved earlier, what
// a->next was before it became NULL)
/*
Now, at the next iteration, progress will equal a, and a will equal b.
So, when I assign a->next = progress, I really say, b->next = a.
and so what we get is: b->a->NULL.
Maybe that gives you an idea of the picture?
What is important here is:
progress = a
and
a = b
Because that determines what a->next will equal:
c->b->a->0
a's next is set to 0
b's next is set to a
c's next is set to b
*/
}
return progress;
}
The basic idea is to detach the head node from the first list and attach it to the head of a second list. Keep repeating until the first list is empty.
Pseudocode:
function reverseList(List X) RETURNS List
Y = null
WHILE X <> null
t = X.next
X.next = Y
Y = X
X = t
ENDWHILE
RETURN Y
ENDfunction
If you wish to leave the original list undisturbed then you can code a copying version recursively with the use of a helper function.
function reverseList(List X) RETURNS List
RETURN reverseListAux(X, null)
ENDfunction
function reverseListAux(List X, List Y) RETURNS List
IF X = null THEN
RETURN Y
ELSE
RETURN reverseListAux(X.next, makeNode(X.data, Y))
ENDfunction
Note that the helper function is tail recursive. This means that you can create a copying reversal using iteration.
function reverseList(List X) RETURNS List
Y = null
WHILE X <> null
Y = makeNode(x.data, Y)
X = X.next
ENDWHILE
RETURN Y
ENDfunction
Reversing a singly-linked list using iteration:
current = head // Point the current pointer to the head of the linked list
while(current != NULL)
{
forward = current->link; // Point to the next node
fforward = forward->link; // Point the next node to next node
fforward->link = forward; // 1->2->3,,,,,,,,,this will point node 3 to node 2
forward->link = current; // This will point node 2 to node 1
if(current == head)
current->link = NULL; // If the current pointer is the head pointer it should point to NULL while reversing
current = current->link; // Traversing the list
}
head = current; // Make the current pointer the head pointer
Implementation of a singly-linked list reversal function:
struct Node
{
int data;
struct Node* link;
}
Node* head = NULL;
void reverseList()
{
Node* previous, *current, *next;
previous = NULL;
current = head;
while(current != NULL)
{
next = current-> link;
current->link = previous;
previous = current;
current = next;
}
head = previous;
}
Here is a simple function to reverse a singly linked list
// Defining Node structure
public class Node {
int value;
Node next;
public Node(int val) {
this.value=val;
}
}
public LinkedList reverse(LinkedList list) {
if(list==null) {
return list;
}
Node current=list.head;
Node previous=null;
Node next;
while(current!=null) {
next=current.next;
current.next=previous;
previous=current;
current=next;
}
list.head=previous;
return list;
}
For better understanding, you can watch this video https://youtu.be/6SYVz-pnVwg
If you want to use recursion:
class Solution {
ListNode root=null;
ListNode helper(ListNode head)
{
if (head.next==null)
{ root= head;
return head;}
helper (head.next).next=head;
head.next=null;
return head;
}
public ListNode reverseList(ListNode head) {
if (head==null)
{
return head;
}
helper(head);
return root;
}
}
public void reverseOrder() {
if(head == null) {
System.out.println("list is empty");
}
else {
Node cn = head;
int count = 0;
while (cn != null) {
count++;
cn = cn.next;
}
Node temp;
for(int i = 1; i<=count; i++) {
temp = head;
for(int j = i; j<count; j++) {
temp = temp.next;
}
System.out.print(temp.data+" ->");
}
System.out.print("null");
}
}