adding a node to a collection using JUNG2 - collections

I am trying to add a node like this ( C.add(n)))
I have this problem:
Exception in thread "main" java.lang.UnsupportedOperationException at java.util.Collections$UnmodifiableCollection.add(Unknown Source))
Non-executable code example:
UndirectedSparseMultigraph<MyNode, MyLink> g = getgraph1();
Collection<MyNode> c = null ;
for( MyNode n : g.getVertices() ){
if( n.id == 3 ){
c = g.getNeighbors(n);
System.out.println(C); C.add(n); }
}

You are trying to use UndirectedSparseMultigraph.getNeighbors(V vertex) to get the Vertices this method returns an unmodifiable collection
public Collection<V> getNeighbors(V vertex) {
...
return Collections.unmodifiableCollection(neighbors);
}
As do
public Collection<V> getVertices()
{
return Collections.unmodifiableCollection(vertex_maps.keySet());
}
and
public Collection<E> getEdges()
{
Collection<E> edges = new ArrayList<E>(directed_edges.keySet());
edges.addAll(undirected_edges.keySet());
return Collections.unmodifiableCollection(edges);
}
Based on your comments it appers that you are trying to add a node n to the collection of its neighbors. If this is the case have your tried replacing
( C.add(n)))
with
g.addEdge(new MyLink(), n, n);
to add a self intersection.

Related

Having problem in conversion from Recursive solution to DP

Given a Binary Tree of size N, find size of the Largest Independent Set(LIS) in it. A subset of all tree nodes is an independent set if there is no edge between any two nodes of the subset. Your task is to complete the function LISS(), which finds the size of the Largest Independent Set.
I came up with this recursive solution.
int rec(struct Node *root,bool t)
{
if(root==NULL)
return 0;
if(t==true)
{
return max(1+rec(root->left,!t)+rec(root->right,!t),rec(root->left,t)+rec(root->right,t));
}
else
{
return max(rec(root->left,!t)+rec(root->right,!t),rec(root->left,t)+rec(root->right,t));
}
}
int LISS(struct Node *root)
{
int x,y;
y=rec(root,true);
return y;
}
To solve this problem via DP, I modified the code as follows, but then it gives wrong answer.
It doesn't even work with Binary tree with distinct elements.
map<int,int> mm;
int rec(struct Node *root,bool t)
{
if(root==NULL)
return 0;
if(mm.find(root->data)!=mm.end())
return mm[root->data];
if(t==true)
{
mm[root->data]=max(1+rec(root->left,!t)+rec(root->right,!t),rec(root->left,t)+rec(root->right,t));
return mm[root->data];
}else
{
mm[root->data]=max(rec(root->left,!t)+rec(root->right,!t),rec(root->left,t)+rec(root->right,t));
return mm[root-s>data];
}
}
int LISS(struct Node *root)
{
//Code here
mm={};
int y=0;
y=rec(root,true);
return max(x,y);
}
What's the mistake?
You have two states in your function but you are memoizing only one state. Let's say for root x,
rec(x,true) = 5 and
rec(x,false) = 10 .
You calculated the rec(x, true) first and saved it in your map "mm" as mm[x] = 5.
So when you are trying to get the value of rec(x, false) it is getting the value of rec(x, true) which is 5.

How to find the time complexity of this recursive function?

I am trying to find the time complexity of the recursive function below. I've tried to draw the tree, but it is confusing because in the if condition the function is called once, and otherwise twice.
To give some context, the function is called on nodes of a tree. The task is to calculate the max rating of each node. The rule is that if you add some node to the rating you can't add it's children to the node, but if you don't add it than you can which children to add or don't.
Here is the function:
static int solve(Node node, boolean take) {
int result;
if(take) {
result = node.rating;
for(Node child : node.children) {
result += solve(child, false);
}
return result;
}
result = 0;
for(Node child : node.children) {
result += Math.max(solve(child, true), solve(child, false));
}
return result;
}

Sum up the tree nodes using Java 8 Streams

Is it possible to sum up the nodes of a tree using Java 8 streams, if possible in a one liner ?
Here is a node class
public class Node
{
private int nodeNum;
ArrayList<Node> children = new ArrayList<>();
public Node(int num)
{
this.nodeNum = num;
}
public int getNodeNum()
{
return nodeNum;
}
public boolean addNode(Node node)
{
return children.add(node);
}
public ArrayList<Node> getNodes()
{
return this.children;
}
}
Normal way to solve this is using a recursion and sum up the node , like the code below.
int getNodeSum(Node node)
{
int total = 0;
if(node.children.isEmpty())
return node.getNodeNum();
else
{
for(Node tempNode:node.children)
{
total+= getNodeSum(tempNode);
}
return total+node.getNodeNum();
}
}
We can use streams to sum up the immediate child nodes but I'm not getting how to move deep and do it recursively using Streams.
This code only solves the problem to a single level. Any ideas?
total = list.stream().filter(Node -> node.children.isEmpty()).map(Node:: getNodeNum).reduce(node.getNodeNum(), (a,b) -> a+b);
One solution to your problem would be to use recursion along with Stream.flatMap.
First, you'd need to add the following helper method to your Node class:
public Stream<Node> allChildren() {
return Stream.concat(
Stream.of(this),
this.children.stream().flatMap(Node::allChildren)); // recursion here
}
This returns a Stream<Node> whose elements are this node and all its descendant nodes.
Then, you could rewrite your getNodeSum method as follows:
int getNodeSum(Node node) {
return node.allChildren()
.mapToInt(Node::getNodeNum)
.sum();
}
This uses the above defined Node.allChildren method along with the Stream.mapToInt and IntStream.sum methods to calculate the total sum.
Alternatively, you could have a Function<Node, Stream<Node>> descendants attribute in your Node class that performs the recursion in place:
private Function<Node, Stream<Node>> descendants =
node -> Stream.concat(
Stream.of(node),
node.children.stream()
.flatMap(this.descendants)); // recursion here: function invoked again
This is a recursive lambda expression, since the function you are defining is at both sides of the = sign. This kind of lambda expressions are allowed only as attributes of a class, i.e. you cannot assign a recursive lambda expression to a local variable.
With that recursive function in place, you could rewrite the allChildren method as follows:
public Stream<Node> allChildren() {
return descendants.apply(this);
}
Finally, the code for your getNodeSum method would be identical to the previous version:
int getNodeSum(Node node) {
return node.allChildren()
.mapToInt(Node::getNodeNum)
.sum();
}
Note: while this approach might result attractive for some people, it might have some drawbacks, i.e. now every instance of the Node class has the descendants attribute, despite not being needed at all. You could circumvect this i.e. by having a Tree class with this recursive function as an attribute, and Node being an inner class (with the descendants attribute removed).
You need to add recusive method for Node class, which wil be join child streams
public Stream<Node> recursiveConcat() {
return Stream.concat(
Stream.of(this),
children.stream().flatMap(Node::recursiveConcat));
}
Then do -
root.recusiveConcat().mapToInt(Node::getNodeNum).sum()
whole code
public class Node {
private int nodeNum;
ArrayList<Node> children = new ArrayList<>();
public Node(int num) {
this.nodeNum = num;
}
public int getNodeNum() {
return nodeNum;
}
public boolean addNode(Node node) {
return children.add(node);
}
public ArrayList<Node> getNodes() {
return this.children;
}
public Stream<Node> recursiveConcat() {
return Stream.concat(
Stream.of(this),
children.stream().flatMap(Node::recursiveConcat));
}
}
Node root = new Node(1);
Node node1 = new Node(2);
Node node2 = new Node(3);
Node node3 = new Node(4);
node2.addNode(node3);
node1.addNode(node2);
root.addNode(node1);
System.out.println(root.recursiveConcat().mapToInt(Node::getNodeNum).sum());

Count the number of nodes of a doubly linked list using recursion

Here is what I've done so far:
struct rep_list {
struct node *head;
struct node *tail;
}
typedef rep_list *list;
int length(const list lst) {
if (lst->head == NULL) {
return 0;
}
else {
lst->head = lst->head->next;
return 1 + length(lst);
}
}
This works, but the head of the list the function accepts as a parameter gets changed. I don't know how to fix that.
I'm not allowed to change the function definition so it should always accept a list variable.
Any ideas?
EDIT: I tried to do what Tyler S suggested in the comments but I encountered another problem. If I create a node* variable at the beginning, it should point to lst->head. But then every recursive call to the function changes the value back to lst->head and I cannot move forward.
You don't need a local node: just don't change the list head. Instead, pass the next pointer as the recursion head.
int length(const list lst) {
if (lst->head == NULL) {
return 0;
}
else {
return 1 + length(lst->head-next);
}
}
I see. Okay; this gets a bit clunky because of the chosen representation. You need a temporary variable to contain the remaining list. This iscludes changing the head.
int length(const list lst) {
if (lst->head == NULL) {
return 0;
}
else {
new_lst = new(list)
new_lst->head = lst->head->next;
var result = 1 + length(new_lst);
free(new_lst)
return result
}
}
At each recursion step, you create a new list object, point it to the 2nd element of the current list, and continue. Does this do the job for you?
Although this solution is clunky and I hate it, its the only way I can see to accomplish what you're asking without modifying the method signature. We create a temporary node * as member data of the class and modify it when we start.
struct rep_list {
struct node *head;
struct node *tail;
}
node *temp = NULL;
bool didSetHead = false;
typedef rep_list *list;
int length(const list lst) {
if ((didSetHead) && (lst->head != temp)) {
temp = lst->head;
didSetHead = false;
}
if (temp == NULL) {
didSetHead = true;
return 0;
}
else {
temp = temp->next;
return 1 + length(temp);
}
}
Please note, I haven't tested this code and you may have to play with a bit, but the idea will work.

Traverse a graph, one vertex, all possible round trips

I have an interesting question at hand. I want to solve a problem of starting from a source vertex of a weighted graph, and find out all possible paths that lead back to it.
For eg: Consider a directed graph above:
Expected Output If I start from Source=A:
1) A -> C -> D -> B-> A
2) A -> B -> A
3) A -> D -> B -> A
Note:
a) The graph will be weighted and I'am finding the sum(not necessarily minimum sum) of the edges as I traverse.
b) Planning to represent the graph using a matrix, and the graph may be Cyclic at some places.
b) Which is the most efficient code that'll solve this? I know about BFS and DFS, but they dont calculate round trips!
Current DFS CODE: (adjacency graph)
void dfs(int cost[][20],int v[],int n, int j)
{
int i;
v[j]=1;
printf("Vistiing %d\n",j);
for(i=0;i<n;i++)
if(cost[j][i]==1 && v[i]==0)
dfs(cost,v,n,i
);
}
This can be solved by modifying DFS (or BFS).
Consider DFS.
Once you visit the nodes mark it as visited. Once you return from it, mark it un-visited so that other paths can be recognized.
Your example:
Start from A.
Choose a path.
A->B->A.
Return to B. No other paths.
Return to A. Mark B unvisited. Choose another path.
A->D->B->A.
Return to B. No other paths.
Return to D. Mark B unvisited. No other paths.
Return to A. Mark D unvisited. Choose another path.
A->C->D->B->A.
Note: The important thing here is to mark the nodes un-visited.
This sounds like a nice application case for Backtracking:
Start with the desired node
If you reached the start node for the second time, return the result
Otherwise: For each neighbor
Add the neighbor to the current path
Do the recursion
Remove the neighbor from the current path
This is implemented here as an example. Of course, this (particularly the graph data structure) is only a quick sketch to show that the idea is feasible, in a MCVE:
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
public class GraphRoundTrips
{
static class Vertex
{
String name;
Vertex(String name)
{
this.name = name;
}
#Override
public String toString()
{
return name;
}
}
static class Edge
{
Vertex v0;
Vertex v1;
Edge(Vertex v0, Vertex v1)
{
this.v0 = v0;
this.v1 = v1;
}
#Override
public String toString()
{
return "("+v0+","+v1+")";
}
}
static class Graph
{
List<Vertex> vertices = new ArrayList<Vertex>();
List<Edge> edges = new ArrayList<Edge>();
void addVertex(Vertex v)
{
vertices.add(v);
}
void addEdge(Edge e)
{
edges.add(e);
}
List<Vertex> getOutNeighbors(Vertex v)
{
List<Vertex> result = new ArrayList<Vertex>();
for (Edge e : edges)
{
if (e.v0.equals(v))
{
result.add(e.v1);
}
}
return result;
}
}
public static void main(String[] args)
{
Vertex A = new Vertex("A");
Vertex B = new Vertex("B");
Vertex C = new Vertex("C");
Vertex D = new Vertex("D");
Graph graph = new Graph();
graph.addVertex(A);
graph.addVertex(B);
graph.addVertex(C);
graph.addVertex(D);
graph.addEdge(new Edge(A,C));
graph.addEdge(new Edge(A,D));
graph.addEdge(new Edge(A,B));
graph.addEdge(new Edge(B,A));
graph.addEdge(new Edge(C,D));
graph.addEdge(new Edge(D,B));
compute(graph, A, null, new LinkedHashSet<Vertex>());
}
private static void compute(Graph g, Vertex startVertex,
Vertex currentVertex, Set<Vertex> currentPath)
{
if (startVertex.equals(currentVertex))
{
List<Vertex> path = new ArrayList<Vertex>();
path.add(startVertex);
path.addAll(currentPath);
System.out.println("Result "+path);
}
if (currentVertex == null)
{
currentVertex = startVertex;
}
List<Vertex> neighbors = g.getOutNeighbors(currentVertex);
for (Vertex neighbor : neighbors)
{
if (!currentPath.contains(neighbor))
{
currentPath.add(neighbor);
compute(g, startVertex, neighbor, currentPath);
currentPath.remove(neighbor);
}
}
}
}

Resources