Can someone explain the algorithm? - java

I need function with parameters as (LinkedList one,LinkedList two)
so, how to set/define the head and current for both the list seperately??
I dont know why this question was closed.
But I am new to java and need to solve this so can anybody help???
to check if a list is subset of another, I have this code from GeeksforGeeks
HERE IT IS CODE IF WE PASS NODE IN THE PARAMETER LIKE (Node one,Node two) but I want parameters as (linkedlist one,liked list two) so can anyone explain algorithm to do so???
static boolean checkSubSet(Node first, Node second) {
Node ptr1 = first, ptr2 = second;
// If both linked lists are empty,
// return true
if (first == null && second == null)
return true;
// Else If one is empty and
// other is not, return false
if (first == null ||
(first != null && second == null))
return false;
// Traverse the second list by
// picking nodes one by one
while (second != null)
{
// Initialize ptr2 with
// current node of second
ptr2 = second;
// Start matching first list
// with second list
while (ptr1 != null)
{
// If second list becomes empty and
// first not then return false
if (ptr2 == null)
return false;
// If data part is same, go to next
// of both lists
else if (ptr1.data == ptr2.data)
{
ptr1 = ptr1.next;
ptr2 = ptr2.next;
}
// If not equal then break the loop
else break;
}
// Return true if first list gets traversed
// completely that means it is matched.
if (ptr1 == null)
return true;
// Initialize ptr1 with first again
ptr1 = first;
// And go to next node of second list
second = second.next;
}
return false;
}
but how to do the same thing by passing the actual linked lists as a parameter for eg
static boolean checkSubSet(Node first, Node second){}
instead of this I want to do this
static boolean checkSubSet(LinkedList<Integer> list1,LinkedList<Integer> list2){}

You are trying to refactor your code so it accepts java.util.LinkedList as an argument. Well, I see that your code is from geeksforgeeks. The geeksforgeeks assumes that you have your own linked list implementation. It also assumes you have access to the next and data parts of the linked list nodes. Unfortunately, java LinkedList does not expose those, so your code is not useful for your question.
You need to design a new algorithm for the Java LinkedList. Since LinkedList is not a Set. It is not very meaningful to execute set functions over a LinkedList. However,
if you really need, you may use something like that:
return new HashSet(a).containsAll(new HashSet(b));
or, iterate over the lists to get what you want.

Related

Recursively delete the last occurrence in a linked list, Java

class Link{
private int value;
private Link next;
}
I am asked to write a recursive method to delete last occurrence of a certain value, say 4.
before 2->3->4->5->4->2
after 2->3->4->5->2
The last occurrence only. I know how to delete all occurrence but I can't tell if its the last occurrence. No helper method is allowed.
The one to delete all occurrence
public Link deleteAll(){
if (next == null){
return value==4? null:this;
}else{
if (value == 4){
return next.deleteAll();
}
next = next.deleteAll();
return this;
}
}
You can declare a pointer to the last occurred node and delete that node when reached the last element in list. Following steps explains that -
Declare two pointers one is next as in your above code another can be temp.
Iterate through list using next like you doing in deleteAll method above.
If you find the node you looking for assign that node to temp.In your case 4.
When next is null you reached the end of list now delete, whatever node is in temp delete that node. If temp is still null than no node found in given key.
EDIT:
Possible pseudo Code in case of recursion:
public void deleteLast(Node node,Node temp,Node prev, int data)
{
if(node==null)
{
if(temp!=null && temp.next.next!=null){
temp.next = temp.next.next;}
if(temp.next.next==null)
temp.next = null;
return;
}
if(node.data==data)
{
temp = prev;
}
prev = node;
deleteLast(node.next, temp, prev, int data);
}
Above code should be able to solve your problem. I made some edit in my approach which should be obvious from the code but let me describe it below
I added a prev pointer. Because if we want to delete a particular node we need to assign its next to prev node's next.So, we need the prev node not the node that we want to delete.
I think this change will follow in iterative approach too.
Not really answering your exact question, but as an alternative option, you might consider the following.
Write a recursive method to delete the first occurrence of a specified value, something like this:
public Link deleteFirst(int target) {
if (value == target) {
return next;
}
next = (next == null) ? null : next.deleteFirst(target);
return this;
}
Then you could write a reverse() method as either an iterative or recursive method as you see fit. I haven't included this, but googling should show some useful ideas.
Finally the method to remove the last occurrence of a value from the linked list could then be written like this:
public Link deleteLast(int target) {
return reverse().deleteFirst(target).reverse();
}
Note that as long as your reverse() method is linear complexity, this operation will be linear complexity as well, although constants will be higher than necessary.
The trick is to do the work on the way back -- there is no need for additional parameters, helpers or assumptions at all:
Link deleteLast(int target) {
if (next == null) {
return null;
}
Link deleted = next.deleteLast(target);
if (deleted == null) {
return value == target ? this : null;
}
if (deleted == next) {
next = deleted.next;
}
return deleted;
}

Java - Convert a Tree to a Lists of Nodes with same depth

I am trying to write a code to convert a binary tree to a lists of nodes with same depth. If a tree has depth d, then d lists will be created. The logic is to do in-order traversal and add the currently traversed node to the list of appropriate depth.
public void treeToListofNodesByLevel(Node<T> n,int depth, ArrayList<LinkedList<Node<T>>> treeList){
if(n.right != null){
inOrderWithHeight(n.right, depth + 1);
}
if(treeList.size() >= depth){
treeList.add(depth, new LinkedList<Node<T>>() );
}
treeList.get(depth).add(n);
if(n.left != null){
inOrderWithHeight(n.left, depth + 1);
}
}
and then calling:
ArrayList<LinkedList<Node<T>>> result = new ArrayList<LinkedList<Node<T>>>();
treeToListofNodesByLevel(root, 0, result);
Will this work ? Are there any corner cases I am not handling ?
Also, right now I am passing the List of List to be returned by the method because I can not think of a way to initialize it in the method and returning it at then end while also maintaining the recursive structure. Is there a better way to do this ?
You have the general concept pretty much perfect. It will work, and should handle all cases.
However, you have a few errors in the details:
Your check for when to add a new list has the comparison in the wrong direction. It should be if (treeList.size() <= depth).
Each call to inOrderWithHeight() (which you haven't provided any code of) should be a recursive call to treeToListofNodesByLevel(). Keep the first two arguments as they are, and just pass the treeList for the third.
This one's more a style issue, but parameter types should generally be declared as the highest level type that satisfies what you actually need. There is no need here to specify ArrayList or LinkedList, any List will do. Change the treeList parameter's type to List<List<Node<T>>>.
For the matter of initializing the List inside the method while also using recursion, that's the sort of thing that implementation helper methods are for. Take the current body of treeToListofNodesByLevel and move it into a private method (with the recursive calls changed so the private method calls itself), let's call it treeToListofNodesByLevelHelper. Then change the current public method to this:
public List<List<Node<T>>> treeToListofNodesByLevel(Node<T> node) {
List<List<Node<T>>> result = new ArrayList<>();
treeToListofNodesByLevelHelper(node, 0, result);
return result;
}
I cannot understand what the method "inOrderWithHeight" is doing. What I do for this question (not optimized) is to traverse like BFS using two queues and for each iteration adding the nodes of that depth to the list of that iteration (each iteration is traversing one depth of the tree). Here is my code to do that for a binary tree as you supposed in your answer:
Queue<Node<T>> queue1 = new LinkedList<Node<T>>() ;
Queue<Node<T>> queue2 = new LinkedList<Node<T>>() ;
public void treeToListofNodesByLevel(Node<T> root, ArrayList<LinkedList<Node<T>>> treeList) {
if (root == null)
return;
int curr_depth = 0;
queue1.add(root);
while(!queue1.isEmpty()){
treeList.add(curr_depth, new LinkedList<Node<T>>());
while(!queue1.isEmpty()){
Node<T> node = queue1.remove();
treeList.get(curr_depth).add(node);
if(node.left != null) queue2.add(node.left);
if(node.right != null) queue2.add(node.right);
}
curr_depth++;
while(!queue2.isEmpty()){
Node<T> node = queue2.remove();
queue1.add(node);
}
}
}
I wrote this on the fly without syntax checking and may have compiler errors. But hopefully you get the idea.
Why you just use the same function the code will be more beautifull :
public void treeToListofNodesByLevel(BinaryTree node, int currentDepth, List<List<BinaryTree>> result){
// Check if the list for the currentDepth is created
if(result.get(currentDepth) != null){
result.add(currentDepth, new ArrayList<BinaryTree>())
}
// Add the current node to the list
result.get(currentDepth).add(node);
// Recursive the left node
if(node.left != null){
treeToListofNodesByLevel(node.left, currentDepth+1, result);
}
// Recursive the right node
if(node.right != null){
treeToListofNodesByLevel(node.right, currentDepth+1, result);
}
}
In your main function :
List<List<BinaryTree>> result = new ArrayList<>();
BinaryTree root = new BinaryTree();
treeToListofNodesByLevel(root, 0, result);

Java Circular Linked List,Remove Node not working properly

Ok so i need to deleted items from a circular list,as part of a bigger program that isnt working, and i cant seem to delete the last node passed in to the delete method, if the index passed in is 1 it will delete the 1st node in list and replace it, but when there is only one node left it has nothing to reference off, been at this hours. i will leave my delete method here
public void delete(int index)
{
if(Node.numOfUsers == 1)
{
first=null;
return;
}
//make curr the same as first node
int i = 1;
curr=first;
//if index passed in is 1, make temporary node same as one after first node
// if(size<1)
// {
// System.out.println("ok so this is where we are at");
// }
if(index==1)
{
temp=first.nextNode;
while(temp.nextNode!=first)
{
temp=temp.nextNode;
}
temp.nextNode=temp.nextNode.nextNode;
first=curr.nextNode;
}
else
{
//as long as i is not equal to node index-1 move current on 1 and increment i by 1
while(i != index-1)
{
curr=curr.nextNode;
i++;
}
//curr.nextNode is pointing to the node index we want and making it equal to one index above it
curr.nextNode=curr.nextNode.nextNode;
}
Node.numOfUsers--;
int size=size();
}
}
Looks like you're keeping track globally of a number of users. If this behaves the way I think it would, you could just have a small check at the beginning of this method so that if it is zero, you don't follow through with any of the logic following it.
if(Node.numOfUsers == 0) return;
This will make it so you don't bother executing any of the other logic.
A slightly better methodology to this problem might be to use the Node you want to delete as a parameter, rather than its index. This way you can avoid having to keep track of indices inside your data structure.
e.g.
public void delete(Node n) {
if(Node.numOfUsers == 0 || n == null) return; // 0 nodes or null parameter.
Node temp = first;
if(temp.next == null) { //only one node
temp = null; //simply delete it
} else {
while(temp.next != n) {
temp = temp.next;
if(temp == first) { //if we circle the entire list and don't find n, it doesn't exist.
return;
}
}
temp.next = n.next; // perform the switch, deleting n
}
}
EDIT: The above code follows the assumption that you'll have references to the node you want to delete. If this is not the case, using indices is just as good. You may also consider comparing values, however this would require you to assume that you have unique values in your nodes (and I don't know what you're restrictions are).
The logic for comparing values would be identical to the above, however instead of comparing if(temp == n) for example, you would compare if(temp.data.equals(n.data)). The use of the .equals() method is specifically for the String type, but you could modify it to work with whatever data type you are expecting, or better yet write a custom .equals method that allows the use of Generics for your abstract data type.

Identify loop or recursion in the list

I want to identify the loop or recursion in the list for the below structure of the node. How can I identify the same?
public class EntityNode {
private EntityNode nextNode; // Points to the next node
}
Example,
Node1 -> Node2 -> Node3 -> Node4 -> Node5 -> Node6 -> Node4
Here, you can see that Node6 is pointing to Node4, and here there comes the looping or recursion and my code will go into infinite. So what if I want to find out this type of scenario with the optimum performance level?
This is actually an interview question I have heard a few times. While I have never tried to implement any sort of loop detection, the answer that most of the interviewers seemed to like is iterating through the list and storing the visited nodes in a hashtable. If you get a collision while storing into the table, then you have a loop in your list.
Edit: In an attempt to offer some code for the example, here is what I would probably try to do (assuming you have some sort of LinkedList<EntityNode> object). I updated this to use a HashSet instead of a HashMap so it was more straightforward (as pointed out by PM 77-1).
public bool detectLoop(LinkedList<EntityNode> list)
{
Set<EntityNode> nodeSet = new HashSet<EntityNode>();
EntityNode curNode = list.getHead();
boolean loopDetected = false;
if(curNode != null)
{
while(curNode.getNextNode() != null && !loopDetected)
{
cureNode = curNode.getNextNode();
loopDetected = !nodeSet.add(curNode);
}
}
return loopDetected;
}
I haven't had the opportunity to test this, but this should work. The reason being that the add() method for a HashSet returns true if this set did not already contain the specified element. So if there is a EntityNode already exists in the set, it will return false, meaning that there was a loop detected.
Since my answer has sort of taken off, I want to say that there are other solutions to this as well. The other one that has been pointed out in this thread is the tortoise and the hare algorithm. You can find more information on that in this thread or at this wiki page.
You should have two EntityNode objects. Both start at Node1. Have the first object move two nodes down, and the second only move one node down. Repeat this until you either reach the end (there was no cycle) or the two objects meet at the same node (there is a cycle).
For your example:
n1: Node1, n2: Node1
n1: Node3, n2: Node2
n1: Node5, n2: Node3
n1: Node4, n2: Node4 -> cycle!!
For pseudocode:
while (n1.nextNode isn't null):
n1 = n1.nextNode.nextNode
n2 = n2.nextnode
if (n1 equals n2): return 'there is a loop!'
I searched on the net and found that this type of problem is called the tortoise and hare algorithm. The Wikipedia page is also here for the same.
As codaddict states in their answer here:
The idea is to have two references to the list and move them at
different speeds. Move one forward by 1 node and the other by 2 nodes.
If the linked list has a loop they will definitely meet.
Else either of the two references(or their next) will become null.
Java code implementing the algorithm:
boolean hasLoop(EntityNode first) {
if (first == null) // list does not exist..so no loop either.
return false;
EntityNode slow, fast; // create two references.
slow = fast = first; // make both refer to the start of the list.
while (true) {
slow = slow.nextNode; // 1 hop.
if (fast.nextNode != null)
fast = fast.nextNode; // 2 hops.
else
return false; // next node null => no loop.
if (slow == null || fast == null) // if either hits null..no loop.
return false;
if (slow == fast) // if the two ever meet...we must have a loop.
return true;
}
}
I think you can make a "visited" flag. Or you can use unintersecting sets, which helps to identify loops in O(N *log N).
P.S. I must admit that this method is more appropriate if you need to build a graph without cycles.
I like Bhavik's answer if you are constrained by memory limits. It doesn't create any possibly large objects to determine the answer.
If there is a loop then the single step and double step methods of walking through the EntityNodes will have to intersect.
Here is sample code to test with -
public class EntityNode {
private EntityNode nextNode = null; // Points to the next node
public static void main(String[] args) {
final EntityNode head = new EntityNode();
// Create small sample (test with even and odd number)
EntityNode tail = head;
for (int i = 0; i < 6; i++) {
EntityNode newNode = new EntityNode();
tail.nextNode = newNode;
tail = newNode;
}
// Add "loop" node
tail.nextNode = head;
System.out.println(detectLoop(head));
}
// Return true if a loop is found
private static boolean detectLoop(EntityNode head) {
boolean loopDetected = false;
if (head != null) {
EntityNode singleStep = head;
EntityNode doubleStep = head;
// If either EntityNode is null and end has been found
while ((singleStep.nextNode != null)
&& (doubleStep.nextNode != null)) {
singleStep = singleStep.nextNode;
// Assert doubleStepper.nextNode != null
doubleStep = doubleStep.nextNode.nextNode;
// If there is a "Collision" then there is a loop
loopDetected = (doubleStep == singleStep);
if (loopDetected) {
break;
}
}
}
return loopDetected;
}
Just traverse the list while keeping every visited node in a hash set. If the node you are adding is ever already present in the set, you have a cycle.
A.-Keep count of the amount of added nodes. Then start a loop through them, while counting the loops. If loopsAmount>nodesAmount, you have recursion.
B.-Keep track of the visited nodes. If a node is visited twice, you have recursion.
C.-Index the nodes while creating them. If node.nextNode.Index-1 != node.Index, you have recursion.

How to convert a list to BSTree recursively?

I tried to convert a List from 3{1{,2{,}},5{4{,},6{,}}}
to a Binary Tree like this
3
1 5
2 4 6
I thought it would be easier to use recursion but I get stuck.
public void ListToTree (ArrayList al) {
Iterator it = al.iterator();
// n is the Tree's root
BSTnode n = new BSTnode(it.next());
recurse(al,it,n);
}
void recurse (ArrayList al, Iterator it, BSTnode n) {
if(!it.hasNext()) return;
Object element = it.next();
if(element=="{"){
recurse(al,it,n.left());
return;
} else if (element==",") {
recurse(al,it,n.right());
return;
} else if (element =="}") {
}
}
I don't know how to proceed and was wondering if it's the right track. Please give me some hints how to solve it. Moreover, I realize I often get stuck on recursive questions. Is it because I always want to break it down? Should I just think top-down and double-check if it's correct? Thanks in advance !
Firstly: are you bound to that terrible list representation? You can easily build a BST based on the BST rules with this code:
void insert(Node n, int value) {
if(n == null) {
n = new Node(value);
} else if(value < n.value) {
if(n.left == null) {
n.left = new Node(value);
return;
}
insert(n.left, value);
} else if(value > n.value) {
if(n.right == null) {
n.right = new Node(value);
return;
}
insert(n.right, value);
}
}
You really don't have to pass the iterator. Just use the values from the list. Also it is usually unadvised to use implementation types in method signatures. (i.e. ArrayList -> List).
Another big mistake here is that you don't use == for value comparison, that is for reference comparison. Use equals instead, but you should downcast the Object after an instanceof test e.g.:
if( element instanceof String) {
String seperator = (String)element;
if("{".equals(separator))
//do sth...
Btw the thing you are missing from the code is the actual insertion and the backwards navigation.
After you found the right subtree by navigating with the {-s and ,-s, check whether the element is an Integer then set it as a value for the current node. Backwards navigation should be in the } branch by either returning one level from the recusion and some tricks or calling the method on the parent of the actual node.
But I don't suggest you to follow this direction, it is much easier to just use the values from the list and the simple insertion method.

Categories

Resources