cycle detection in undirected graph using disjointsets? - java

I am implementing the code for cycle detection in undirected graph using find/union methods of disjointsets.
Here is the implementation:
public boolean isCyclicundirected(){
int k;
ArrayDisjointSet set = new ArrayDisjointSet(5);
//Set<Vertex> parents = new HashSet<Vertex>();
System.out.println(vertexMap);
Set<String> allVertices = vertexMap.keySet();
for (String v : allVertices){
Iterator<Edge> e = vertexMap.get(v).adj.iterator();
while (e.hasNext()){
int i = Integer.parseInt(vertexMap.get(v).name);
int j = Integer.parseInt(e.next().target.name);
if (set.isConnected(i, j))
return true;
else
k = set.join(i, j);
System.out.println(set);
}
}
return false;
}
and here is the isConnected of disjoinset
public boolean isConnected(int i, int j){
return find(i)==find(j);
}
if two nodes have the same root, (returned by find), that indicates there is a cycle.
For a graph like this which has no cycles (1,2),(2,3),(3,4), my method returns true.
I am failing to understand what is wrong.
EDIT latest: After suggestions below:
public boolean isCyclicundirected() {
int k;
HashSet<HashSet<Vertex>> vertexpairs = new HashSet<HashSet<Vertex>>();
ArrayDisjointSet set = new ArrayDisjointSet(100);
Set<String> allVertices = vertexMap.keySet();
for (String v : allVertices) {
Vertex current = vertexMap.get(v);
for (Edge e : current.adj){
Vertex nextVertex = e.target;
HashSet<Vertex> temp = new HashSet<Vertex>();
temp.add(nextVertex);
temp.add(current);
if (!vertexpairs.contains(temp)) {
vertexpairs.add(temp);
int i = Integer.parseInt(current.name);
int j = Integer.parseInt(nextVertex.name);
if (set.isConnected(i, j))
return true;
else
k = set.join(i, j);
System.out.println(set);
}
}
}
return false;
}
I get node:java.util.NoSuchElementException

You iterate over each edge twice, once from each side. You need to only consider any edge once.

Related

Represent a graph containing directed and undirected edges using List<Integer>

I was asked this question in one of my google interviews. I couldn't figure it out. If someone can help that would be great :)
The class provided was
class Node{
int data,
List<Node> outEdges;
}
if you're provided a Node stream containing both directed and undirected edges you have to encode it in such a way that it return List and and decode again to original graph
List<Integer> encode(Node root){
}
Node decode(List<Integer> graph){
}
The hint provided was you can add your own integers if you want
You could just put the data and all the edges in the list and using null as delimiter:
private class IndexAndEdge {
public Set<Integer> edges = new HashSet<>();
public int index;
public int data;
}
List<Integer> encode(Node root) {
List<Integer> result = new ArrayList<>();
Map<Node, IndexAndEdge> lookup = new HashMap<>();
parse(root, lookup);
result.add(lookup.size());
lookup.values().stream()
.sorted((a, b) -> Integer.compare(a.index, b.index))
.forEach(iae -> {
result.add(iae.data);
result.addAll(iae.edges);
result.add(null);
});
result.remove(result.size() - 1);
return result;
}
private int parse(Node node, Map<Node, IndexAndEdge> lookup) {
if (lookup.containsKey(node))
return lookup.get(node).index;
IndexAndEdge iae = new IndexAndEdge();
iae.index = lookup.size();
iae.data = node.data;
lookup.put(node, iae);
for (Node n : node.outEdges)
iae.edges.add(parse(n, lookup));
return iae.index;
}
Node decode(List<Integer> graph) {
Node[] nodes = new Node[graph.get(0)];
for (int i = 0; i < nodes.length; i++) {
nodes[i] = new Node();
nodes[i].outEdges = new ArrayList<>();
}
int index = 0;
for (int i = 1; i < graph.size(); i++) {
Integer n = graph.get(i);
if (n == null)
index++;
else if (nodes[index].outEdges.isEmpty())
nodes[index].data = n;
else
nodes[index].outEdges.add(nodes[n]);
}
return nodes[0];
}

I am trying to do BFS search but get Runtime Error Index out Of Bounds Exception

Given a directed graph, the task is to do Breadth First Traversal of this graph starting from 0.
Complete the Function bfsOfGraph() to return Breadth First Traversal of given graph.
Here, V denotes the number of vertices.
Here's the problem link
class Solution
{
public ArrayList<Integer> bfsOfGraph(int V , ArrayList<ArrayList<Integer>> adj)
{
ArrayList<Integer> bfs = new ArrayList<>();
boolean vis[] = new boolean[V+1];
for( int i = 1; i < V+1 ; i++){
if(vis[i] == false){
Queue<Integer> q = new LinkedList<>();
q.add(i);
vis[i] = true;
while(!q.isEmpty()){
Integer node = q.poll();
bfs.add(node);
for(Integer it : adj.get(node)){
if(vis[it] == false){
vis[it] = true;
q.add(it);
}
}
}
}
}
return bfs;
}
}
When you know you have started (origin of the graph) from 0 then why are calling on each node (vertex) of the graph. I think you misunderstood the questions. You have to apply BFS on the Origin 0. You Might get the IndexOutOfBound Exception as well because all the vertex of the graphs is from 0 to V-1 inclusive. I can see you are treating the graph vertex as 1 to V inclusive.
public ArrayList<Integer> bfsOfGraph(int V,ArrayList<ArrayList<Integer>> adj)
{
Queue<Integer> queue = new LinkedList<>();
boolean visited[] = new boolean[V];
ArrayList<Integer> results = new ArrayList<>();
queue.add(0);
while(!queue.isEmpty()){
Integer nextNode = queue.poll();
results.add(nextNode);
visited[nextNode] = true;
if(adj.get(nextNode) != null){
for(int neighbor : adj.get(nextNode)){
if(!visited[neighbor]){
queue.add(neighbor);
visited[neighbor] = true;
}
}
}
}
return results;
}

How to create a grab method in Java that deals with Generics and Arrays

So, I am creating a generic data structure named "Sack". In this, I add items to a sack, grab a random item, see if it's empty, or dump out its contents etc. Also, I'm creating it to expand to hold as many items as needed.
I need to create a grab method that should randomly remove and return an item from the sack. If no items are present, it should return null.
My code is the following:
public class Sack<E>
{
public static final int DEFAULT_CAPACITY = 10;
private E [] elementData;
private int size;
#SuppressWarnings("unchecked")
public Sack()
{
elementData = (E[]) new Object[DEFAULT_CAPACITY];
}
#SuppressWarnings("unchecked")
public Sack(int capacity)
{
if(capacity < 0)
{
throw new IllegalArgumentException("capacity " + capacity);
}
this.elementData = (E[]) new Object[capacity];
}
public boolean isEmpty()
{
if(size == 0)
{
return true;
}
else
{
return false;
}
}
public void add(E item)
{
int index = size++;
if(size >= elementData.length-1)
{
elementData = Arrays.copyOf(elementData, size);
}
elementData[index] = item;
}
public E [] dump()
{
E [] E2 = Arrays.copyOf(elementData, size);
for(int i = 0; i < size; i++)
{
elementData[i] = null;
}
size = 0;
return E2;
}
My grab method is right here.
public E [] grab()
{
E [] E2 = Arrays.copyOf(elementData, size);
return elementData;
}
It is incorrect, I receive an error when I run my tests stating AssertionFailedError: grab is not working correctly (check with empty sack)
==>
Expected: null
Actual : [Ljava.lang.Object;#76908cc0
My tests are right here, I cannot modify my tests, only the code provided as there is an error there, I need help on what I previously stated:
the grab method should randomly remove and return an item from the sack. If no items are
present, it should return null
Therefore, here are my tests:
#Test
public void testGrab()
{
assertNull(s.grab(), "grab is not working correctly (check with empty sack)");
Random rand = new Random();
int numElements = rand.nextInt(9) + 1;
Integer[] setElementData = new Integer[10];
ArrayList<Integer> expectedElements = new ArrayList<Integer>();
int randElement;
for(int i=0; i<numElements; ++i) {
randElement = rand.nextInt(50) + 1;
if(!expectedElements.contains(randElement)) {
setElementData[i] = randElement;
expectedElements.add(randElement);
} else {
--i;
}
}
try {
elementData.set(s, setElementData);
size.set(s, numElements);
for(int i=0; i<numElements; ++i) {
expectedElements.remove(s.grab());
assertEquals(numElements-i-1, size.get(s), "grab is not working correctly (check size usage)");
}
assertEquals(0, expectedElements.size(), "grab is not working correctly (check size usage)");
} catch (Exception e) {
fail("grab is not working correctly");
}
}
Let me know if you have any solutions for my grab method on how to accomplish this task.
I don't understand why your grab method returns an array instead of a single element. I can suggest you a different approach
public class Sack<E> {
private final static int DEFAULT_CAPACITY = 10;
private final static float REALLOC_FACTOR = 1.5f;
private E[] elementData;
private int size;
public Sack() {
this(DEFAULT_CAPACITY);
}
#SuppressWarnings("unchecked")
public Sack(int capacity) {
if(capacity <= 0)
throw new IllegalArgumentException("capacity " + capacity);
elementData = (E[]) new Object[capacity];
}
public boolean isEmpty() {
return size == 0;
}
public void add(E item) {
int index = size++;
if(size > elementData.length-1)
elementData = Arrays.copyOf(elementData, (int)(size*REALLOC_FACTOR));
elementData[index] = item;
}
public E [] dump() {
E [] E2 = Arrays.copyOf(elementData, size);
Arrays.fill(elementData, null);
size = 0;
return E2;
}
public E grab() {
if(size == 0)
return null;
int index = (int)(Math.random()*size);
E element = elementData[index];
elementData[index] = elementData[size-1];
elementData[size-1] = null;
size--;
return element;
}
}
The idea behind this grab method is to select a random index rand (from 0 to effectiveSize-1) and to return this element, but before we have to swap this element with the last element (the element with index effectiveSize-1) and reduce the effective size. I have used Math.rand() because when it is first called, it creates a single new pseudorandom-number generator and then this generator is used thereafter for all calls to this method.
Note: I've also added a realloc factor to avoid the array realloc for each element, after the array is saturated.
Here is the answer broken down a little more simply. I give credit to #Mirko Alicastro.
public E grab()
{
if(size == 0)
return null;
int index = (int) (Math.random() * size);
E element = elementData[index];
elementData[index] = elementData[size - 1];
elementData[size - 1] = null;
size--;
return element;
}
Here's another way of solving this method,
public E grab()
{
if(isEmpty())
{
return null;
}
Random rand = new Random();
int i = rand.nextInt(size);
E item = elementData[i];
remove(i);
return item;
}

BFS: Shortest Reach in a Graph

I am working to get the shortest reach in a graph problem in hackercode. I have designed a code and some testcases are fine whereas some testcases are terminated due to timeout.
Could you say where I need to optimize and please also comment about code style. I am looking for the ways to improve it.
Following is my code,
public class BFS {
public static class Graph {
public Node[] nodes;
Stack<Node> stack = new Stack<Node>();
public Graph(int size) {
nodes = new Node[size];
}
public void addEdge(int first, int second) {
Node nodeF = getNode(first);
if (nodeF == null) {
nodeF = new Node();
nodeF.nodeVal = first;
}
Node nodeS = getNode(second);
if (nodeS == null) {
nodeS = new Node();
nodeS.nodeVal = second;
}
nodeF.neighbours.add(nodeS);
nodes[first] = nodeF;
nodes[second] = nodeS;
}
public int[] shortestReach(int startId) { // 0 indexed
stack.push(getNode(startId));
int[] distance = new int[nodes.length];
Arrays.fill(distance, -1);
distance[startId] = 0;
while (!stack.isEmpty()) {
Node currentNode = stack.pop();
Set<Node> children = getChildren(currentNode);
for (Node node : children) {
distance[node.nodeVal] = distance[currentNode.nodeVal] + 6;
stack.add(node);
}
}
return distance;
}
public Set<Node> getChildren(Node givenNode) {
for (Node node : nodes) {
if (node == givenNode) {
return node.neighbours;
}
}
return null;
}
public Node getNode(int index) {
return nodes[index];
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int queries = scanner.nextInt();
for (int t = 0; t < queries; t++) {
// Create a graph of size n where each edge weight is 6:
Graph graph = new Graph(scanner.nextInt());
int m = scanner.nextInt();
// read and set edges
for (int i = 0; i < m; i++) {
int u = scanner.nextInt() - 1;
int v = scanner.nextInt() - 1;
// add each edge to the graph
graph.addEdge(u, v);
}
// Find shortest reach from node s
int startId = scanner.nextInt() - 1;
int[] distances = graph.shortestReach(startId);
for (int i = 0; i < distances.length; i++) {
if (i != startId) {
if (distances[i] == 0)
continue;
System.out.print(distances[i]);
System.out.print(" ");
}
}
System.out.println();
}
scanner.close();
}
}
class Node {
public int nodeVal;
public Set<Node> neighbours = new HashSet<Node>();
}

Finding all hamiltonian cycles

I'm trying to implement a method for adding all possible Hamiltonian cycles to a list using recursion. So far my stopping condition isn't sufficient and I get "OutOfMemoryError: Java heap space" in the line that adds a vertex to a list:
private boolean getHamiltonianCycles(int first, int v, int[] parent,
boolean[] isVisited, List<List<Integer>> cycles) {
isVisited[v] = true;
if (allVisited(isVisited) && neighbors.get(v).contains(new Integer(first))) {
ArrayList<Integer> cycle = new ArrayList<>();
int vertex = v;
while (vertex != -1) {
cycle.add(vertex);
vertex = parent[vertex];
}
cycles.add(cycle);
return true;
} else if (allVisited(isVisited)) {
isVisited[v] = false;
return false;
}
boolean cycleExists = false;
for (int i = 0; i < neighbors.get(v).size(); i++) {
int u = neighbors.get(v).get(i);
parent[u] = v;
if (!isVisited[u]
&& getHamiltonianCycles(first, u, parent, isVisited, cycles)) {
cycleExists = true;
}
}
//if (!cycleExists) {
isVisited[v] = false; // Backtrack
//}
return cycleExists;
}
Can someone please suggest me what I'm doing wrong or is my approach completely incorrect?
EDIT:
As suggested in comments, the culprit was the parent array, causing an infinite loop. I wasn't able to correct it and I changed the array to store the child element. Now everything seems to work:
private boolean getHamiltonianCycles(int first, int v, int[] next,
boolean[] isVisited, List<List<Integer>> cycles) {
isVisited[v] = true;
if (allVisited(isVisited) && neighbors.get(v).contains(first)) {
ArrayList<Integer> cycle = new ArrayList<>();
int vertex = first;
while (vertex != -1) {
cycle.add(vertex);
vertex = next[vertex];
}
cycles.add(cycle);
isVisited[v] = false;
return true;
}
boolean cycleExists = false;
for (int u : neighbors.get(v)) {
next[v] = u;
if (!isVisited[u]
&& getHamiltonianCycles(first, u, next, isVisited, cycles)) {
cycleExists = true;
}
}
next[v] = -1;
isVisited[v] = false; // Backtrack
return cycleExists;
}
If you is looking for Disjoint Hamiltonian Cycles here have an implementation using Backtracking.

Categories