detecting circular reference - java

So in an interview, I was actually asked a simple question that goes like this, say that I have a nested JSON response, [a, b, c ,d [a, [b, [d, e], g], h]. I am asked to implement a class that basically can handle to store this data and a print method to do so, so here's what I have:
public class JSONode
{
private String str;
private JSONode nodes;
public JSONode (String a, ArrayList<String> n)
{
str = a;
nodes = n;
}
}
public class JSONResp
{
private ArrayList<JSONode> arr;
public JSONResp ()
{
arr = new ArrayList<JSONode>();
}
public boolean checkCircular(JSONode temp)
{
for (int i = 0; i < arr.size(); i++)
{
if (arr.get(i).nodes == temp)
return true;
}
return false;
}
public void add (JSONode nd)
{
if (!checkCircular(nd))
arr.add(nd);
}
public void recurseJSONode(JSONode)
{
if (!JSONode.node)
System.out.print(JSONode.str);
else {
System.out.print(JSONode.str);
recurseJSONode(JSONode.node);
}
}
public void print()
{
for (int i = 0; i < arr.size(); i++)
recurseJSONode(arr.get(i));
}
public static void main (String[] args) {
JSONResp x = new JSONResp();
x.add(new JSONode("a", null);
x.add(new JSONode("b", null);
}
}
Now he said that there will circular references issues when I print, in other words I have list A = [a, b, c, D] and D = [q, t, y, A]. So he said I'd have to prevent from adding D by using the checkCircular above. I made an attempt. Also just a node I know my recurseJSONode isn't correct and so does the print, so looking for a suggestion to fix that as well.. I am just curious to this problem.

The reason your circular check isn't right is that you only look for an existing duplicate of JSONode under the one node you're trying to add it to. But A might be under B and B is under A, so each is unique within its parent's list.
Re: using a stack for tracking activity in a recursive function:
Set<SomeNodeType> stack = new HashSet<SomeNodeType>();
someRecursiveThing(rootNode, stack);
And then inside someRecursiveThing:
void someRecursiveThing(SomeNodeType under, Set<SomeNodeType> stack) {
if (!stack.add(under)) {
return;
// continue happily, e.g. call self with child node,
// passing down the stack
SomeNodeType child = ...
someRecursiveThing(child, stack)
// finish by removing 'under' from the stack:
stack.remove(under);
}
The advantage of HashSet is that add and remove typically run in constant time - the size of the tree is irrelevant.
For comparison:
Markus Lausberg's answer suggests doing a complete recursive search of the whole tree, which would be O(N) where N is the number of nodes in the tree, and as you are doing that check for every node it ends up being O(N^2). A tree of 10 nodes will do 100 node comparisons; a tree of 1000 nodes will do 1000,0000 node comparisons.
In kan's answer the check involves searching the parent chain, which will depend on the depth of the tree. For a perfectly lopsided tree (worst case) the depth will be the same as the number of nodes, giving O(N^2) again. For a balanced tree the depth will be ~log N, not much better (remember, the check has to be done for every node).
The effect of these differences depends on the comparison operation used to determine if two nodes are the same. If it is just a pointer comparison (i.e. you only care if they're the same object) and the tree is never very large, the overhead of HashSet may have a negative impact. Whereas if you need to compare two nodes in a more complex way, so each comparison is expensive, and the tree is large, then the optimised lookup of HashSet will become beneficial.

First of all it should be like
public class JSONode
{
private String str;
private ArrayList<JSONode> nodes;
public JSONode (String a, ArrayList<JSONode> n)
{
str = a;
nodes = n;
}
}
You have to check recursivly, if the given node is part of the parent node and the parent of the parent and so on...
So more like
public static boolean checkCircular(JSONode temp)
{
if(temp == null){
return false;
}
ArrayList<JSONode> pNodes = temp.getChildrens();
for (int i = 0; i < nodes.size(); i++)
{
if (pNodes.get(i).getString().equals(temp.getString()))
return true;
if(checkCircular(temp))
return true;
}
return false;
}

Related

Why does the last 2 elements gets repeated in the following implementation of double-ended list?

This is the Main class with main method for generating a double-ended list, remove and display its elements.
public class Main {
Link first, last;
public static void main(String args[]) {
Main ob = new Main();
Link arr[] = {
new Link(1), new Link(2), new Link(3)
};
int len = 3;
for(int i=0;i<len;i++)
ob.insertFirst(arr[i]);
System.out.print("Data in the list: ");
while(ob.first!=null)
System.out.print(ob.removeAndReturn()+", ");
for(int i=0;i<len;i++)
ob.insertLast(arr[i]);
System.out.print("\nData in the list: ");
while(ob.first!=null)
System.out.print(ob.removeAndReturn()+", ");
}
void insertFirst(Link arg) {
if(isEmpty())
last = arg;
arg.next = first;
first = arg;
}
// This removeAndReturn() method returns the Object data the link is holding and removes that Link from the list
Object removeAndReturn() {
Object ret = null;
try {
ret = first.data;
if(first.next==null)
last = null;
first = first.next;
}catch(NullPointerException NPe) {
System.out.println("You are referring to a null.\nLinked List is empty.");
}
return ret;
}
void insertLast(Link arg) {
if(isEmpty())
first = arg;
else
last.next = arg;
last = arg;
}
boolean isEmpty() {
return first==null;
}
}
class Link {
Object data;
Link next;
Link(Object data) {
this.data = data;
}
}
When executing, it gives the following output:
Data in the list: 3, 2, 1,
Data in the list: 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, ... {truncated}
Here the last two elements gets repeated in the output. I tried nullifying both the Link variables first and last before calling ob.insertLast(arr[i]) but it gives the same output.
Update:
private keywords are removed from the complete method signature for methods in the Main class other than main(String args[]) method and rmF() method is changed to removeAndReturn().
The main problem in your code lies in the fact that you're using the exact same nodes (the ones within the arr) to fill your list with head and tail insertions.
In fact, once you perform your first head insertion, those nodes have been linked to each other like this:
(3) => (2) => (1) => null
So, when you're performing your second insertion, you have that node 1 points to node 2, node 2 points to node 3, and theoretically node 3 should point to null since it's supposed to be the last element. However, node 3's next field is still pointing to node 2 from the previous insertion. This creates a loop where node 2 and node 3 keep pointing at each other; thus yielding the infinite loop you're experiencing.
(1) => (2) => <= (3)
To fix your problem you could either reset the next field of your nodes before re-using them (poor solution) or work with the actual data you need to structure rather than the nodes. In fact, the user of your class shouldn't be bothered with the details of your implementation and should only care about the info to be stored/represented (in your case int numbers).
This is a possible solution to your problem:
public class Main {
Link first, last;
public static void main(String args[]) {
Main ob = new Main();
//Array of int not of links
int[] arr = {1, 2, 3};
int len = 3;
for (int i = 0; i < len; i++)
ob.insertFirst(arr[i]);
System.out.print("Data in the list: ");
while (ob.first != null)
System.out.print(ob.removeAndReturn() + ", ");
for (int i = 0; i < len; i++)
ob.insertLast(arr[i]);
System.out.print("\nData in the list: ");
while (ob.first != null)
System.out.print(ob.removeAndReturn() + ", ");
}
//------ CORRECTION ------
//The method should receive the info the user needs to store.
//It will then be up to you to represent it as a Link or whatever
//internal structure you're going to use tomorrow. Don't bind the
//user to your internal implementation.
//------------------------
void insertFirst(int arg) {
//Generating a new node (or link) based on the given info
Link l = new Link(arg);
if (isEmpty())
last = l;
l.next = first;
first = l;
}
// This removeAndReturn() method returns the Object data the link is holding and removes that Link from the list
Object removeAndReturn() {
Object ret = null;
try {
ret = first.data;
if (first.next == null)
last = null;
first = first.next;
} catch (NullPointerException NPe) {
System.out.println("You are referring to a null.\nLinked List is empty.");
}
return ret;
}
//-------- CORRECTION --------
//same explanation given above
//----------------------------
void insertLast(int arg) {
//Generating a new node (or link) based on the given info
Link l = new Link(arg);
if (isEmpty())
first = l;
else
last.next = l;
last = l;
}
boolean isEmpty() {
return first == null;
}
}
Lastly, Do not capture RuntimeException. These are unchecked exceptions, not checked. You should investigate on their origin rather than simply catching them. What you've written is a bad practice.
https://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html
As #JayC667 has already said, you could improve some designing and naming of your class, methods and variables. There are some conventions, especially when talking about data structures. For example:
Your class is called Main but it describes a List, a name like MyList would have been better.
Your utility class, Link, could have been placed within MyList as a static nested class and probably named Node (it's a better fit).
Some of your methods' names were a bit too cryptic. Self-explanatory names will better help the users of your class.
Avoid accessing the internal state of another object from outside (list.first != null). Methods should be your way to go to interrogate an object's state.
Using generic types could have been a better implementation than just Object as generics provide: strict checks at compile time, avoid casting a more type safety, the ability to re-use the same code for different data types.
https://docs.oracle.com/javase/tutorial/java/generics/why.html
Here is a link to an implementation with the suggestions made above:
https://www.jdoodle.com/iembed/v0/s7C

Avoiding duplicate entries in an array

I am writing a method that adds Vertex objects to an array. I need to check if the vertex I am adding already exists in the array. I am not sure where I am going wrong. Here is my method:
public void addVertex(Vertex v) {
if (activeVertices >= maxVertices) {
System.out.println("Graph full");
return;
}
for(int i=1; i<vertices.length; i++) {
if(vertices[i] != vertices[i-1]){
vertices[activeVertices] = v; // add vertex to list of vertices
v.graphIndex = activeVertices; // record index of vertex in graph
activeVertices++; // increment vertex count
}
}
}
Vertex class:
public class Vertex {
public String name;
public int graphIndex; // index of adjacency matrix position of node in graph
public Vertex (String s) {
name = s;
graphIndex = -1; // invalid position by default
}
public String toString() {
return name;
}
}
The class that contains the addVertex() method:
public class Graph {
private int maxVertices;
private Vertex[] vertices; // array of nodes
private int[][] edges; // adjacency matrix
int activeVertices;
public Graph(int maxSize) {
maxVertices = maxSize;
vertices = new Vertex[maxVertices];
activeVertices = 0;
}
public void addVertex(Vertex v) {
if (activeVertices >= maxVertices) {
System.out.println("Graph full");
return;
}
for(int i=1; i<vertices.length; i++) {
if(vertices[i] != vertices[i-1]){
vertices[activeVertices] = v; // add vertex to list of vertices
v.graphIndex = activeVertices; // record index of vertex in graph
activeVertices++; // increment vertex count
}
}
}
public void addEdge(Vertex v1, Vertex v2, int w) {
edges[v1.graphIndex][v2.graphIndex] = w;
edges[v2.graphIndex][v1.graphIndex] = w;
}
public Graph minimumSpanningTree() {
Graph mst = new Graph(maxVertices); // create new graph
int[] set = new int[activeVertices];
for (int i=0; i<activeVertices; i++) { // copy nodes to graph
mst.addVertex(vertices[i]);
set[i]=i; // assign each node to its own set
}
PriorityQueue q = new PriorityQueue(maxVertices*maxVertices); // create priority queue
for (int i=0; i<activeVertices; i++) { // copy edges to queue
for (int j=0; j<activeVertices; j++) {
if (edges[i][j]!=0) {
q.enqueue(new Edge(vertices[i],vertices[j],edges[i][j]));
}
}
}
while (!q.isEmpty()) { // iterate over all edges in priority order
Edge e = q.dequeue(); // consider next edge
if (set[e.source.graphIndex]!=set[e.destination.graphIndex]) { // skip edges not connecting different sets
mst.addEdge(e.source, e.destination, e.weight); // add edge to MST
System.out.println("adding "+e);
int setToMerge=set[e.destination.graphIndex]; // rename nodes from "other" set
for (int i=0; i<activeVertices; i++) {
if (set[i]==setToMerge) { // find nodes from "other" set
set[i]=set[e.source.graphIndex]; // reassign nodes
}
}
}
}
return mst;
}
public void print() {
System.out.format(" ");
for (int i=0; i<activeVertices; i++) {
System.out.format("%3s ", vertices[i].name);
}
System.out.format("\n");
for (int j=0; j<activeVertices; j++) {
System.out.format("%3s ", vertices[j].name);
for (int i=0; i<activeVertices; i++) {
System.out.format("%3d ", edges[i][j]);
}
System.out.format("\n");
}
}
}
First, you should be using equals instead of ==. You should write a proper equals method in your Vertex class (use Google to find plenty of tutorials on how to do this).
For example, if you wanted two Vertex objects to be considered equal only when their names were the same, then your equals method would look something like this:
public boolean equals(Object obj) {
if(obj == null) {
return false;
}
if(obj instanceof Vertex) {
Vertex otherVertex = (Vertex) obj;
if(this.name.equals(otherVertex.name)) {
return true;
}
}
return false;
}
If you wanted to compare graphIndex as well, then you would need to check that in the equals method as well.
Assuming you have a proper equals method in your Vertex class, the simplest solution would be to use the ArrayUtils.contains method, from the Apache Commons library (Apache Commons has TONS of useful methods, which can save you a lot of time. You should check it out). This method takes in an array and an Object, and checks if the array contains the object or not.
You're always checking vertices[1] against vertices[0] and adding based on the result. You're not checking for v, and not actually looking in the whole array.
If an == check (identity, not equivalence) is really what you want, then:
public void addVertex(Vertex v) {
if (activeVertices >= maxVertices) {
System.out.println("Graph full");
return;
}
for(int i=0; i<vertices.length; i++) {
if(vertices[i] == v){
// Already have it
return;
}
}
vertices[activeVertices] = v; // add vertex to list of vertices
v.graphIndex = activeVertices; // record index of vertex in graph
activeVertices++; // increment vertex count
}
If you want equivalence instead, replace
if(vertices[i] == v){
with
if(v.equals(vertices[i])){
Side note: Based on your having an activeVertices variable, I suspect you may be better off with ArrayList<Vertex> rather than Vertex[]. That would also give you the contains method (which uses equals), which may be able to replace your loop (if you want an equals, not ==, check).
Whenever you write a value class, i.e. a class that represents a value or quantity of something, you should always override the following methods for your class:
equals(Object o);
hashCode();
Not all classes are value classes. Some represent system resources and others represent actions or processes, but whenever a class is written as an abstraction for a collection of data you should always consider writing the above methods.
The reason is straightforward. Whereas Java primitives have only value, Java reference types (which include all the instances of classes you write yourself) have both value and location. This confers the properties of both equality and identity to reference types and they are very different.
By default, the equals() method in the Object class performs an identity comparison and NOT an equality comparison ... and it's a good thing too. Because any subclass of Object can have vastly different notions of "how instances can be considered equal" there is no straightforward way that Object could have a superclass method that would test equality for any arbitrary Java object. In contrast, it is always straightforward to test for identity. If any two references indicate the same location, then their objects are identical. This exemplifies the different notions of equality and identity.
You need to be able to test whether your Vertex instances are equal and not whether they are identical. For this reason, you really do need to override the equals(Object o) method. If you also override hashCode() (which you should), then you may be able to store your vertices in a HashSet, which would guarantee that no two vertices would be equal.

Insert in a sorted Array-Queue

I'm working on sorted Queues like a Priority Queue. I already did it with a List, and it already worked great. Now I'd like to do it with a array. But I have a little logical Problem with add a new Element and insert it into the sorted array.
The final output should be like that:
Priority: 5 Value: x
Priority: 4 Value: iso
.... (and so on)
So the Element with the highest Priorithy should be on index = 0.
I just don't know (and yes I know it's really simply to switch it, but I just can't do it :/) how to do it...
I already tried a few things but I'm stuck... :/ can please anyone help?
Here's my code:
public class Queue {
private QueueElem[] a;
public Queue(int capacity)
{
QueueElem[] tempQueue = new QueueElem[capacity];
a= tempQueue;
}
public void enqueue(int p, String v)
{
QueueElem neu = new QueueElem(p,v);
int i=0;
while(i<a.length)
{
if (a[i] == null)
{
a[i] = neu;
break;
}
i++;
}
}
public void writeQueue()
{
int i=0;
while((i< a.length) && (a[i] != null))
{
System.out.println("Priority: " + a[i].priority + " Value: " + a[i].value);
i++;
}
}
public static void main(String args[])
{
Queue neu = new Queue(10);
neu.enqueue(4,"iso");
neu.enqueue(2,"abc");
neu.enqueue(5,"x");
neu.enqueue(1,"abc");
neu.enqueue(4,"bap");
neu.enqueue(2,"xvf");
neu.enqueue(4,"buep");
}
}//end class Queue
class QueueElem {
int priority;
String value = new String();
public QueueElem(){ }
public QueueElem(int p, String v)
{
this.priority = p;
this.value = v;
}
public int getPrio()
{
return this.priority;
}
public String getValue()
{
return this.value;
}
}
It would be better if you interpreted your array as a max-heap. That is the typical way to implement priority queue.
What you're looking for, if you're trying to maintain a sorted array for your priority queue, is to implement insertion sort (sort of; you don't have an unsorted array to start with. You have an empty array that you simply add to, while maintaining a sorted order). Every time you insert a new element, you will iterate through the array to find the correct spot and then insert it there, after shifting the elment currently at that spot, and everything after it one spot down. Note that this is not as performant as implementing this using a heap, since at worst you have O(n) performance every time you insert, whereas with a heap you have O(logn).
I don't understand why anyone would want to work with raw arrays... especially now that you have implemented it with a List.
If you want to see how to insert an element in a raw array, look in the code of ArrayList, since underneath it uses a raw array. You'll have to move all the elements to right of the insertion point, which you could copy in a loop, or by using System.arraycopy(). But the nastiest part is that you will likely have to create a new array since the array size increases by one when you add an element (it depends if you are using an array that has exactly the size of your data, or a larger array, as is done in ArrayList).

How to create Priority Queue that sorts based on certain attribute of class?

I have created a Node class:
public class Node {
int vertex;
double latency;
Node predecessor;}
public double getLatency()
{
return latency;
}
I want to create a Priority Queue that sorts the Nodes by latency from least to greatest. After research, I believe I need to override the Comparator?
PriorityQueue<Node> pqueue = new PriorityQueue<Node>(numVertices, new Comparator<Node>({
#Override
???
}
}
I'm not too sure how to override it.
You just actually need to compare both latencies. That means overriding the method compare of the class Comparator comparing the latency of both input Node:
PriorityQueue<Node> pqueue = new PriorityQueue<Node>(numVertices, new Comparator<Node>({
#Override
public int compare(Node a, Node b) {
return Integer.compare(a.getLatency(), b.getLatency());
}
}
However this only works for Java 7, for other versions:
new Integer(a.getLatency()).compareTo(new Integer(b.getLatency()));
If you don't want to create a new Object then compare both int as usual
The "???" in your example can be replaced with the following:
public int compare(Node a, Node b) {
if (a.getLatency() < b.getLatency())
return -1;
else if (a.getLatency() > b.getLatency())
return 1;
return 0;
}

Iterators over Tries in Java

I am currently trying to implement a trie data structure for integer tuples. And have implemented as follows:
import java.util.ArrayList;
public class TrieNode {
int num;
ArrayList<TrieNode> links;
boolean endOfTuple;
public TrieNode(int num)
{
this.num = num;
links = new ArrayList<TrieNode>();
this.endOfTuple = false;
}
}
I then have a trie class as follows:
public class Trie {
TrieNode root;
public Trie() {
root = new TrieNode(-1);
}
public void insertTuple(int[] tuple)
{
int l = tuple.length;
TrieNode curNode = root;
for (int i = 0; i < l; i++)
{
TrieNode node = new TrieNode(tuple[i]);
if(!curNode.links.contains(node)){
curNode.links.add(node);
}
curNode = curNode.links.get(curNode.links.indexOf(node));
}
curNode.endOfTuple = true;
}
}
I can add values to this trie, but i need to be able to iterate over this and was wondering how i could do this? For example if i wanted to print the tree using an iterator...Any help will be great...
All you need for an interator is to implement the Iterator interface, which only requires that you supply boolean hasNext() and Integer next(). So the question to ask is: how do represent a position in your trie, such that it's possible to (a) fetch the value associated with that position, and (b) figure out the "next" position given a current one?
I'll refrain from posting an actual solution since I'm not sure whether this is homework. But consider: you can represent a "current position" in your trie just by choosing a particular trie node, and the path of trie nodes you used to reach it. Then you can compute the "next" element recursively: if the current element is a node that has children, then find the first child for which endOfTuple is true. If the current element doesn't have children, then go to its parent and advance to that parent's next child. If that parent doesn't have next children, then go it its parent's next child, etc.

Categories

Resources