I have a minimum spanning tree and I am using DFS to traverse it where the datastructure of my graph is an adjancancy list. I want to get the edge with the maximum weight to every node from the source and store it in an array, this is what I have so far:
void recDFS(int currVertex, int source, int[] visited, int maxWeight){
visited[currVertex] = 1;
Vector<IntegerPair> neighbours = MSTAdjList.get(currVertex);
for(int j = 0; j < neighbours.size(); j++){
int neighbourWeight = neighbours.get(j)._second // get weight of neighbour
int neighbourIndex = neighbours.get(j)._first; // get index of neighbour
if (neighbourWeight > maxWeight)
maxWeight = neighbourWeight;
bigArrayWithValues[source][neighbourIndex] = maxWeight; // Store each value
recDFS(neighbourIndex, source, visited, maxWeight); // Call next neighbour
}
}
This won't work because when the recursion breaks, the value of maxWeight will still have the "old" value, while I want the edge with max weight to each node from the source that is fixed.. Any help would be appreciated.
Related
I was solving this problem, Actually I did finish it. However, I still want to enhance my solution. Like is there another approach to solve this problem so the time complexity is reduced? my solution's time complextiy is O(n^2). Furthermore, I thought about a way to solve it recursively, but at the end I mixed the both; as I will traverse "Iteratively" to get numOfNodes and then traverse "Recursively" to count the last nodes. I did not implement it yet but I am confused about that solution and I do not know if it is right or not!
**please have a look at the code first ,,,,,,,,,,,,,,,,,,,,,
The idea about it is to count to numOfNodes in the list, and then come over and traverse again but for each node I will reduce the numOfNodes. and when numOfNodes == k, then the sum is being calculated using a for loop.
Here is the code:
public int sum(Node head, int k){
int sum = 0;
int numOfNodes = 0;
Node temp = new Node(0);
temp = head;
while(temp != null){
numOfNodes++;
temp = temp.next;
}
temp = head;
while(temp != null){
if(numOfNodes == k){
for(int i = 0; i<k; i++){
sum += temp.data;
temp = temp.next;
}
}else{
numOfNodes--;
temp = temp.next;
}
}
return sum;
}
Thank you in advance!
Your code is optimistic about the number of nodes in the list. It will return 0 when the list has fewer than k nodes. I would think that in that case the sum of all nodes should be returned.
As to the rest of the algorithm: it is fine. It uses constant auxiliary memory and runs in linear time. It is not quadratic as you thought: although you loop a second time through the list, this just makes the number of iterations O(2n), which still is O(n).
You could also combine the two iterations into one, by keeping track of a second node reference that lags k nodes behind the leading node reference.
Here is how that would look:
public static int sum(Node head, int k){
int total = 0;
Node lag = head;
Node lead = head;
while (lead != null) {
if (--k < 0) {
total -= lag.data;
lag = lag.next;
}
total += lead.data;
lead = lead.next;
}
return total;
}
A recursive solution has as downside that it will need O(k) stack space.
Assuming you want to keep space complexity constant O(1), your solution looks optimal. I am also assuming it is a singly linked list.
By the way, time complexity of your solution is not O(n^2). It is O(n). Your are doing one traversal to get total count. That is O(n).
You are doing another traversal to get the k nodes count. These are two independent traversals. So time complexity is n + n = 2n or O(n). There is no inner loop, so your solution works in O(n) time complexity.
Your iterative solution looks fine, although I would suggest simplifying your actual counting code to something like this:
Node temp = head;
for(int i=0; i<numOfNodes-k; i++)
temp = temp.next;
// temp now points to the first node to be counted
int sum = 0;
for(int i=0; i<k; i++)
{
sum += temp.data;
temp = temp.next;
}
return sum;
The recursive solution you mentioned has the advantage of only having to traverse the list once, counting the top k nodes on the way back. Note that we have to use a reference value, (I'm using a simple one-element array), to hold the calculated limit above which we should count nodes.
static int sumr(Node node, int pos, int k, int[] lim)
{
if(node == null)
{
// pos now holds the length of the list
lim[0] = pos-k;
return 0;
}
int sum = sumr(node.next, pos+1, k, lim);
if(pos >= lim[0]) sum += node.data;
return sum;
}
Called via:
int sum = sumr(head, 0, 3, new int[1]);
It can be easily done in O(N) Time and O(1) Space complexity.
The idea is to iterate the list once and count the number of nodes in the list. Let the size of the list be size.
Now iterate the list once again and keep track of visited nodes. If i is in the desired range (last k nodes) then add the values of those nodes to the resultant sum.
int i=1;
int sum = 0;
Node pointer = head;
while (pointer != null)
{
if ((size-k) <= i)
{
sum += pointer.data;
}
i++;
pointer = pointer.next;
}
So I have a gird that can be any given size (i.e. matrix or 2d array). Each element contains a value and simply I need to find the shortest path. However, the problem I am having is trying to represent this grid as a graph or adj matrix or what ever you are meant to do. For example this is my code:
public int shortestPath (int[][] matrix, int sr, int sc, int dr, int dc)
{
int p = matrix.length * matrix[0].length;
int[] distances = new int[p];
boolean[] visited = new boolean[p]; //I think all are set to false by default
for (int i = 0; i < p; i++)
{
distances[i] = Integer.MAX_VALUE;
}
PriorityQueue<Node> pq = new Priority<>(); // a Node holds the int row, int col and the distance from source cell. It also orders by distances, so therefore a comparable was created to change natural order.
pq.add(new Node(sr,sc,0);
distances[(sr * matrix[0].length) + sc] = 0;
visited[(sr * matrix[0].length) + sc] = true;
while(!pq.isEmpty())
{
Node n = pq.poll();
int row = n.getRow();
int col = n.getColumn();
int dist = n.getDistance();
//Now here with a normal graph I would search neighbours via a for loop and find in the adj list where an element = 1 and is not visited. This is where I am stuck
}
}
So obviously with a grid, I will need to find neighbours of left/right/up/down (not doing diagonals). Thus, I need to take into account boundaries. How can a create an Adj matrix or what is the correct way to start searching neighbours for a grid like this?
I am having bad luck with this today because most examples show in graph form to adj matrix and not from grid form to adj matrix.
There's a trick for grid graphs:
lets say {x,y} denotes difference between 2 neighbour cells
You know neighbours will be in {0,-1}, {0,1}, {1,0} or {-1,0} (assuming no diagonal moves), or those cells will be out of bounds
Save arrays of those differences:
int differenceX[] = {0,0,1,-1};
int differenceY[] = {-1,1,0,0};
Now you can use for loop for neighbours:
for(int i=0; i<4; i++)
{
int neighRow = row + differenceY[i];
int neighCol = col + differenceX[i];
if(min(neighRow, neighCol) >= 0 && neighRow < matrix.length && neighCol < matrix[0].length){
//process node
}
}
I read that the only difference between a B Tree and a B* Tree is the fill factor. The minimum fill factor of a B-Tree is 1/2, and the minimum fill factor for a B* tree is 2/3.
So, for a B-Tree, the max number of keys and children you have is 2*degree (minimum number of elements in a node). If I have a minimum fill factor of 3, the most keys a node can have is 6. That logic gives me this:
keyHolder = new int[2 * degree - 1];
children = new BTreeNode[2 * degree];
That worked just fine and my B-Tree worked as expected. So, when I went to modify my B-Tree into a B* tree, I thought that the max number of children and keys must be (3 * degree)/2. That gave me this:
keyHolder = new int[((3 * degree)/2) - 1];
children = new BStarTreeNode[(3 * degree)/2];
Problem:
However, now the split child method throws an array out of bounds exception when I try to copy keys from temp here:
temp.keyHolder[j] = node.keyHolder[j + degree];
Question:
I'm not really asking why the code doesn't work, but rather, what's wrong with my logic. If the only difference between the two trees is just the fill factor, shouldn't the only thing you need to do to convert one to another is change the max number of keys and children for a given node? Everything else, including how you split the nodes up once the root is full should stay the same. You just need to change the max limit at which the split takes place right?
Thanks for any help in advance.
Relevant Code:
I placed the splitChild method below in case it helps:
public void splitChild(int i, BStarTreeNode node) {
BStarTreeNode temp = new BStarTreeNode(node.degree - 1, node.leaf);
temp.numKeys = degree - 1;
// Copy the degree-1 keys into temo from node
for (int j = 0; j < degree - 1; j++) {
temp.keyHolder[j] = node.keyHolder[j + degree];
}
// If this node is not a leaf, copy the degree children
if (node.leaf == false) {
for (int j = 0; j < degree; j++) {
temp.children[j] = node.children[j + degree];
}
}
// Reduce the number of keys in node
node.numKeys = degree - 1;
// Since this node is going to have a new child,
// create space of new child
for (int j = numKeys; j >= i + 1; j--) {
children[j + 1] = children[j];
}
// Link the new child to this node
children[i + 1] = temp;
//Find location of
// new key and move all greater keys one space ahead
for (int j = numKeys - 1; j >= i; j--) {
keyHolder[j + 1] = keyHolder[j];
}
// Copy the middle key of node
keyHolder[i] = node.keyHolder[degree - 1];
// Increment count of keys in this node
numKeys = numKeys + 1;
}
The code I wrote is from here. I just rewrote it in Java.
The maximum number of keys per node doesn't change. It is still 2N. What changes is the conditions where you must split and join.
When you split a full node you must acquire keys from the previous and successor nodes, so that the two new nodes satisfy n >= 2*N/3, and conversely when joining you must distribute keys back into the prior and successor nodes, as you will have too many keys for just one node.
I have an directed graph that is represented by an adjacency matrix, where a -1 is indicative of a disconnect between two nodes.
My goal is to find and sum up each source node in the graph (i.e. any node that contains to edges coming into it).
I currently have a O(n^2) routine that checks each cell of a given row, and at each cell flips the indices to see if there exists an edge coming into the node I'm currently looking at.
I have a int used to keep track of how many source nodes I've come across so far, and a boolean that becomes marked every time I come across a node that isn't a source node.
Throughout continuous testing of my code, I found that each time returned me 0 source nodes, though I know my graph contains at least 1. I've written the following method...
In this method, size represents the number of nodes that exist in the graph and m is the adjacency matrix.
public int numSources() {
int sources = 0;
boolean isSource = true;
for( int i = 0; i < size; i++ ) {
for( int j = 0; j < size; j++ ) {
if( m[j][i] != -1) {
isSource = false;
break;
}
}
if( isSource ) {
sources++;
} else {
isSource = true;
}
}
return sources;
}
I have a file with each line consisting of int int int where the first two ints indicate two nodes in the graph and the third represents the edge cost between them
Being new to algorithms and having searched all over the web, including some answers on stackoverflow, I still find myself asking how I find the distance between those nodes in a simple matrix.
First of all, the simple matrix:
public class MatrixRoutes {
int[][] position; // matrix
int size;
MatrixRoutes(int dimentions) {
posicion = new int[dimentions][dimentions];
size= dimensiones;
}
}
I set the size of the matrix with a simple
MatrixRoutes r = new MatrixRoutes(5);
Cool! I have my empty grid!
Populating it with the most simple of data, distances:
r.position[0][1] = 1;
r.position[1][1] = 0;
r.position[0][2] = 2;
r.position[2][2] = 0;
r.position[0][3] = 3;
r.position[3][3] = 0;
r.position[0][4] = 4;
r.position[4][4] = 0;
r.position[0][5] = 5;
r.position[5][5] = 0;
There's my test distance matrix, all ready to be tested.
Alright, got my nodes with distances. Now it's a matter of finding the shortest distance. I've been reading about different algorithms and their implementations with Java.
I've wanted to implement Dijkstra's algorithm, but it seems to only accept one starting number, used as a distance variable? That's not what I need when I need the distance between two variables.
Here's my attempt at implementing the algorithm:
private static int buscarRutaMasRapida(MatrixRoutes g, int nodeOrigin, int nodeDestiny)
{
int[] found = new int[g.position.length];
boolean[] visitedNode = new boolean[g.position.length];
int max = 999;
for (int i = 0; i < g.position.length; i++)
{
mejor[i] = max;
visitedNode [i] = false;
}
found[nodeOrigin+ nodeDestiny] = nodeOrigin + nodeDestiny;
for(int i = 0; i < g.position.length; i++)
{
int min = max;
int nodoNow = nodeOrigin;
for (int j = 0; j < g.position.length; j++)
{
if (!visitedNode [j] && found [j] < min)
{
nodoNow = j;
min = found [j];
}
}
visitedNode [nodoNow ] = true;
for (int j = 0; j < g.position.length; j++)
{
if (g.position[nodoNow ][j] < max && found[nodoNow ] + g.position[nodoNow ][j] < found [j])
{
found[j] = found [nodoNow ] + g.position[nodoNow ][j];
}
}
}
return found [g.position.length - 2];
}
All I'm asking is someone who would know of an algorithm which would find the shortest distance between two nodes in either a normal adjacency matrix or distance matrix.
Dijkstra's is the (my) preferred route. It takes in one node and finds the shortest path to all other nodes. Usually for distance between two nodes one would create a check inside Dijkstra's to return when the desired "end" node is reached.
In fact, Wikipedia has very nice psuedocode for you to use.
So for instance in the first step of Dijkstra's, you need to find the distance from the origin point S, you would look at all distances from S to other nodes and put this into your priority queue:
queue.add(position[S][x]); //Do this for all x adjacent to S
If you need to store the distance between each point then repeated use of Dijstraka's algorithm is inefficient if the adjacency graph is dense.
Instead you want the Floyd-Warshall algorithm.
From the wikipedia page, Dijstraka's will have a running time of O(V E log V ) while Floyd-Warshall will be O(V^3). In a connected graph E is between V (singly connected) and V^2 (each node connected to every other node), so the best will really depend on your data.