DFS java pathfinding problems - java

I'm developing a search algorithm for finding paths in a graph. In this algorithm i need to find all the paths in an undirected, not weighted graph that go trough each graph connection only once.
Currently, what my prgoram is doing, is finding all the paths that go trough each node only once. I need connections and not nodes.
Here is my code:
import java.util.*;
public class dfs {
private static Map<Integer, LinkedHashSet<Integer>> map = new HashMap<Integer, LinkedHashSet<Integer>>();
private int startNode;
private int numLinks;
public dfs(int startNode, int numLinks) {
super();
this.startNode = startNode;
this.numLinks = numLinks;
}
public int getNumLinks(){
return numLinks;
}
public void addEdge(int source, int destiny) {
LinkedHashSet<Integer> adjacente = map.get(source);
if(adjacente==null) {
adjacente = new LinkedHashSet<Integer>();
map.put(source, adjacente);
}
adjacente.add(destiny);
}
public void addLink(int source, int destiny) {
addEdge(source, destiny);
addEdge(destiny, source);
}
public LinkedList<Integer> adjacentNodes(int adj) {
LinkedHashSet<Integer> adjacente = map.get(adj);
System.out.println("adjacentes:" + adjacente);
if(adjacente==null) {
return new LinkedList<Integer>();
}
return new LinkedList<Integer>(adjacente);
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int numVertices = input.nextInt();
int numLinks = input.nextInt();
int startNode = input.nextInt();
int endNode = startNode;
dfs mapa = new dfs(startNode, numLinks);
for(int i = 0; i<numLinks; i++){
mapa.addLink(input.nextInt(), input.nextInt());
}
List<ArrayList<Integer>> paths = new ArrayList<ArrayList<Integer>>();
List<Integer> visited = new ArrayList<Integer>();
visited.add(startNode);
Integer currentNode = 0;
Iterator it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pairs = (Map.Entry)it.next();
currentNode = (Integer) pairs.getKey();
mapa.findAllPaths(mapa, visited, paths, currentNode);
}
}
private void findAllPaths(dfs mapa, List<Integer> visited,
List<ArrayList<Integer>> paths, Integer currentNode) {
if (currentNode.equals(startNode)) {
paths.add(new ArrayList<Integer>(visited));
LinkedList<Integer> nodes = mapa.adjacentNodes(currentNode);
for (Integer node : nodes) {
List<Integer> temp = new ArrayList<Integer>();
temp.addAll(visited);
temp.add(node);
System.out.println("temp:" + temp);
findAllPaths(mapa, temp, paths, node);
}
}
else {
LinkedList<Integer> nodes = mapa.adjacentNodes(currentNode);
System.out.println("currentNode:" + currentNode);
List<Integer> inseridos = new ArrayList<Integer>();
for (Integer node : nodes) {
if (visited.contains(node)) {
continue;
}
List<Integer> temp = new ArrayList<Integer>();
inseridos.add(currentNode);
temp.addAll(visited);
System.out.println("visited:" + visited);
temp.add(node);
findAllPaths(mapa, temp, paths, node);
}
}
}
}
Right now, i think the following code:
if (visited.contains(node)) {
continue;
}
is making that the program not going through each node more than once.
I need helping transforming my program to go trough each connection only once, and not through each node only once.
(I'm sorry about my english, i'm not a native)

If you're willing to do some rewriting, I think this kind of problem is more cleanly expressed in an OO fashion.
You could build a linked graph out of Node and Edge instances, allowing you to mark visited edges as you traverse the graph.
class Node
{
List<Edge> adjacentEdges;
boolean isVisited;
}
class Edge
{
Node node1;
Node node2;
boolean isVisited;
}

Related

How to do DFS and BFS in Adjacency List?

Creating a Adjacency List
HashMap <Interger,ArrayList<Integer>> adjList = new HashMap<Integer,ArrayList<Integer>>();
// adding element in Adjacency list (Undirected)
void AdjList(Integer a, Integer b){
adjList.putIfAbsent(a, new ArrayList<>());
adjList.get(a).add(b);
adjList.putIfAbsent(b, new ArrayList<>());
adjList.get(b).add(a);
}
How to do DFS and BFS in this?
I've tried something like this. how to loop through ?
void DFS(Integer i) {
//gettting first element from adjlist
if (adjList.containsKey(i)) {
Integer ele1 = adjList.get(i).get(adjList.get(i).size() - 1);
if (adjList.containsKey(ele1)) {
Integer ele2 = adjList.get(ele1).get(adjList.get(ele1).size() - 1);
}
}
}
You are creating Adjacency List correctly(but it is better to name this function something like adjList), but for both BFS and DFS, you need to have a visited status per node, and iterate over all nodes neighbors of a node and do the BFS/DFS recursively on them.
import java.util.*;
public class Graph {
public static void main(String[] args) {
Graph g = new Graph();
g.adjList(0, 1);
g.adjList(0, 2);
g.adjList(1, 3);
g.adjList(2, 3);
g.DFS(0);
g.BFS(0);
}
HashMap<Integer, ArrayList<Integer>> adjList = new HashMap<>();
// adding element in Adjacency list (Undirected)
void adjList(Integer a, Integer b) {
adjList.putIfAbsent(a, new ArrayList<>());
adjList.get(a).add(b);
adjList.putIfAbsent(b, new ArrayList<>());
adjList.get(b).add(a);
}
void dfsRecursive(int v, boolean[] visited) {
visited[v] = true;
System.out.print(v + " ");
for (int n : adjList.get(v)) {
if (!visited[n])
dfsRecursive(n, visited);
}
}
void DFS(int s) {
boolean[] visited = new boolean[adjList.size()];
System.out.print("DFS: ");
dfsRecursive(s, visited);
System.out.println();
}
void BFS(int s) {
boolean[] visited = new boolean[adjList.size()];
LinkedList<Integer> queue = new LinkedList<>();
visited[s] = true;
queue.add(s);
System.out.print("BFS: ");
while (queue.size() != 0) {
s = queue.poll();
System.out.print(s + " ");
for (int n : adjList.get(s)) {
if (!visited[n]) {
visited[n] = true;
queue.add(n);
}
}
}
}
}
The output of above code would be:
DFS: 0 1 3 2
BFS: 0 1 2 3

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];
}

LinkedList for each index in the LinkedList Array

What is the problem here?.I'm trying to implement the graph data structure,using the adjacency lists,by utilising the Collections from the util package.Here
LinkedList array which holds some integer.
Each element of that LinkedList holds another LinkedList of type: node.
But during the compilation process, it says incompatible types.
How to resolve this problem?
//Sum of dependencies in a graph
import java.util.*;
class node
{
int vertex,weight;
public node(int v,int w)
{
vertex = v;
weight = w;
}
}
public class dependency
{
int V;
LinkedList<Integer> adj[];
public dependency(int v)
{
V = v;
adj = new LinkedList<Integer>[v];
for (int i=0;i < v ;i++ ) {
adj[i] = new LinkedList<node>();
}
}
void addEdge(int v,node l)
{
adj[v].add(l);
}
void BFS(int s)
{
boolean visited[] = new boolean[V];
LinkedList<Integer> queue = new LinkedList<Integer>();
visited[s] = true;
queue.add(s);
while(queue.size() != 0)
{
s = queue.poll();
System.out.println(s+" ");
Iterator<Integer> i = adj[s].listIterator();
while(i.hasNext())
{
int n = i.next();
if(!visited[n])
{
visited[n] = true;
queue.add(n);
}
}
}
}
public static void main(String[] args) {
graph g = new graph(4);
node a = new node(1,10);
node b = new node(2,20);
node c = new node(2,30);
node d = new node(0,20);
node e = new node(3,30);
node f = new node(3,20);
g.addEdge(0, a);
g.addEdge(0, b);
g.addEdge(1, c);
g.addEdge(2, d);
g.addEdge(2, e);
g.addEdge(3, f);
System.out.println("Following is Breadth First Traversal "+
"(starting from vertex 2)");
g.BFS(2);
}
}
You've declared an array of LinkedLists of type LinkedList<Integer>, but you're trying to store LinkedList<node> in the array. It doesn't appear that you're ever using the weight attribute of node, so you should change adj[i] = new LinkedList<node>(); to adj[i] = new LinkedList<Integer>();.

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>();
}

Use PriorityQueue as a minHeap

When trying to solve this problem https://www.hackerrank.com/challenges/cut-the-tree
I was trying to always pick and cut a leaf and then combine its weight to the node that it connects.
I was using a PriorityQueue to store all the nodes, and using the size of their adjacent nodes as the priority. But when I'm trying some test case, it seems that the priority queue property is violated, which means that non-leaf nodes may appear before leaf nodes. Will PriorityQueue automatically update itself or should I call some function to update it. My temporary solution is to use a list to store all the leaves.
The following is my code:
public class Solution {
private static class Node implements Comparable<Node> {
int index;
int value;
Map<Integer, Node> adj;
public Node(int index, int value) {
this.index = index;
this.value = value;
this.adj = new HashMap<Integer, Node>();
}
#Override
public int compareTo(Node n) {
return adj.size() - n.adj.size();
}
}
public static void main(String[] args) {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(new FileInputStream("input.txt")));
int total = 0;
int N = Integer.parseInt(br.readLine());
String[] strs = br.readLine().split(" ");
HashMap<Integer, Node> nodes = new HashMap<Integer, Node>();
for (int i = 0; i < N; i++) {
int value = Integer.parseInt(strs[i]);
nodes.put(i, new Node(i, value));
total += value;
}
for (int i = 0; i < N - 1; i++) {
strs = br.readLine().split(" ");
int n1 = Integer.parseInt(strs[0]) - 1;
int n2 = Integer.parseInt(strs[1]) - 1;
nodes.get(n1).adj.put(n2, nodes.get(n2));
nodes.get(n2).adj.put(n1, nodes.get(n1));
}
// PriorityQueue<Node> pq = new PriorityQueue<Node>(nodes.values());
// while (!pq.isEmpty()) {
// Node n = pq.poll();
// System.out.println(n.index + " " + n.adj.size());
// }
// NOTE: java's PriorityQueue doesn't support update, cannot use it
// LAME DESIGN. use a LinkedList instead
List<Node> leaves = new LinkedList<Node>();
for (Node node : nodes.values()) {
if (node.adj.size() == 1) {
leaves.add(node);
}
}
int minDiff = Integer.MAX_VALUE;
while (!leaves.isEmpty()) {
// get a leaf node
// Node leaf = pq.poll();
Node leaf = leaves.get(0);
leaves.remove(0);
if (leaf.adj.size() <= 0)// last node
break;
int diff = Math.abs((total - leaf.value) - leaf.value);
if (diff < minDiff)
minDiff = diff;
// combind leaf to it's connection
Node conn = null;
for (Node node : leaf.adj.values()) {
conn = node;
}
conn.value += leaf.value;
conn.adj.remove(leaf.index);
if (conn.adj.size() == 1)
leaves.add(conn);
nodes.remove(leaf.index);
}
System.out.println(minDiff);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Thanks.
The standard Java PriorityQueue does not support update. If you need to remove items, then you have to implement your own minHeap. Call heapify when you removed some items in the heap.
The implementation and explanation can be found here!
PrioirtyQueue does not have an implementation but LinkedHashMap does, they are removeEldestEntry.
According to documentation:
The removeEldestEntry(Map.Entry) method may be overridden to impose a policy for removing stale mappings automatically when new mappings are added to the map.

Categories