Approximation Algorithm for non-intersecting paths in a grid - algorithm

I recently came across this question and thought I could share it here, since I wasn't able to get it.
We are given a 5*5 grid numbered from 1-25, and a set of 5 pairs of points,that are start and end points of a path on the grid.
Now we need to find 5 corresponding paths for the 5 pairs of points, such that no two paths should overlap. Also note that only vertical and horizontal moves are allowed. Also the combined 5 path should cover the entire grid.
For example we are given the pair of points as:
P={1,22},{4,17},{5,18},{9,13},{20,23}
Then the corresponding paths will be
1-6-11-16-21-22
4-3-2-7-12-17
5-10-15-14-19-18
9-8-13
20-25-24-23
What I have thought of so far:
Maybe i can compute all paths from source to destination for all pairs of points and then check if there's no common point in the paths. However this seems to be of higher time complexity.
Can anyone propose a better algorithm? I would be glad if one could explain through a pseudo code.Thanks

This problem is essentially the Hamiltonian path/cycle problem problem (since you can connect the end of one path to the start of another, and consider all the five paths as a part of one big cycle). There are no known efficient algorithms for this, as the problem is NP-complete, so you do essentially need to try all possible paths with backtracking (there are fancier algorithms, but they're not much faster).
Your title asks for an approximation algorithm, but this is not an optimization problem - it's not the case that some solutions are better than others; all correct solutions are equally good, and if it isn't correct, then it's completely wrong - so there is no possibility for approximation.
Edit: The below is a solution to the original problem posted by the OP, which did not include the "all cells must be covered" constraint. I'm leaving it up for those that might face the original problem.
This can be solved with a maximum flow algorithm, such as Edmonds-Karp.
The trick is to model the grid as a graph where there are two nodes per grid cell; one "outgoing" node and one "incoming" node. For each adjacent pair of cells, there are edges from the "outgoing" node in either cell to the "incoming" node in the other cell. Within each cell, there is also an edge from the "incoming" to the "outgoing" node. Each edge has the capacity 1. Create one global source node that has an edge to all the start nodes, and one global sink node to which all end nodes have an edge.
Then, run the flow algorithm; the resulting flow shows the non-intersecting paths.
This works because all flow coming in to a cell must pass through the "internal" edge from the "incoming" to the "ougoing" node, and as such, the flow through each cell is limited to 1 - therefore, no paths will intersect. Also, Edmonds-Karp (and all Floyd-Warshall based flow algorithms) will produce integer flows as long as all capacities are integers.

Here's a program written in Python that walks all potential paths. It uses recursion and backtracking to find the paths, and it marks a grid to see which locations are already being used.
One key optimization is that it marks the start and end points on the grid (10 of the 25 points).
Another optimization is that it generates all moves from each point before starting the "walk" across the grid. For example, from point 1 the moves are to points 2 & 6; from point 7, the moves are to points 2, 6, 8 & 12.
points = [(1,22), (4,17), (5,18), (9,13), (20,23)]
paths = []
# find all moves from each position 0-25
moves = [None] # set position 0 with None
for i in range(1,26):
m = []
if i % 5 != 0: # move right
m.append(i+1)
if i % 5 != 1: # move left
m.append(i-1)
if i > 5: # move up
m.append(i-5)
if i < 21: # move down
m.append(i+5)
moves.append(m)
# Recursive function to walk path 'p' from 'start' to 'end'
def walk(p, start, end):
for m in moves[start]: # try all moves from this point
paths[p].append(m) # keep track of our path
if m == end: # reached the end point for this path?
if p+1 == len(points): # no more paths?
if None not in grid[1:]: # full coverage?
print
for i,path in enumerate(paths):
print "%d." % (i+1), '-'.join(map(str, path))
else:
_start, _end = points[p+1] # now try to walk the next path
walk(p+1, _start, _end)
elif grid[m] is None: # can we walk onto the next grid spot?
grid[m] = p # mark this spot as taken
walk(p, m, end)
grid[m] = None # unmark this spot
paths[p].pop() # backtrack on this path
grid = [None for i in range(26)] # initialize the grid as empty points
for p in range(len(points)):
start, end = points[p]
paths.append([start]) # initialize path with its starting point
grid[start] = grid[end] = p # optimization: pre-set the known points
start, end = points[0]
walk(0, start, end)

Well, I started out thinking about a brute force algorithm, and I left that below, but it turns out it's actually simpler to search for all answers rather than generate all configurations and test for valid answers. Here's the search code, which ended up looking much like #Brent Washburne's. It runs in 53 milliseconds on my laptop.
import java.util.Arrays;
class Puzzle {
final int path[][];
final int grid[] = new int[25];
Puzzle(int[][] path) {
// Make the path endpoints 0-based for Java arrays.
this.path = Arrays.asList(path).stream().map(pair -> {
return new int[] { pair[0] - 1, pair[1] - 1 };
}).toArray(int[][]::new);
}
void print() {
System.out.println();
for (int i = 0; i < grid.length; i += 5)
System.out.println(
Arrays.toString(Arrays.copyOfRange(grid, i, i + 5)));
}
void findPaths(int ip, int i) {
if (grid[i] != -1) return; // backtrack
grid[i] = ip; // mark visited
if(i == path[ip][1]) // path complete
if (ip < path.length - 1) findPaths(ip + 1, path[ip + 1][0]); // find next path
else print(); // solution complete
else { // continue with current path
if (i < 20) findPaths(ip, i + 5);
if (i > 4) findPaths(ip, i - 5);
if (i % 5 < 4) findPaths(ip, i + 1);
if (i % 5 > 0) findPaths(ip, i - 1);
}
grid[i] = -1; // unmark
}
void solve() {
Arrays.fill(grid, -1);
findPaths(0, path[0][0]);
}
public static void main(String[] args) {
new Puzzle(new int[][]{{1, 22}, {4, 17}, {5, 18}, {9, 13}, {20, 23}}).solve();
}
}
Old, bad answer
This problem is doable by brute force if you think about it "backward:" assign all the grid squares to paths and test to see if the assignment is valid. There are 25 grid squares and you need to construct 5 paths, each with 2 endpoints. So you know the paths these 10 points lie on. All that's left is to label the remaining 15 squares with the paths they lie on. There are 5 possibilities for each, so 5^15 in all. That's about 30 billion. All that's left is to build an efficient checker that says whether a given assignment is a set of 5 valid paths. This is simple to do by linear time search. The code below finds your solution in about 2 minutes and takes a bit under 11 minutes to test exhaustively on my MacBook:
import java.util.Arrays;
public class Hacking {
static class Puzzle {
final int path[][];
final int grid[] = new int[25];
Puzzle(int[][] path) { this.path = path; }
void print() {
System.out.println();
for (int i = 0; i < grid.length; i += 5)
System.out.println(
Arrays.toString(Arrays.copyOfRange(grid, i, i + 5)));
}
boolean trace(int p, int i, int goal) {
if (grid[i] != p) return false;
grid[i] = -1; // mark visited
boolean rtn =
i == goal ? !Arrays.asList(grid).contains(p) : nsew(p, i, goal);
grid[i] = p; // unmark
return rtn;
}
boolean nsew(int p, int i, int goal) {
if (i < 20 && trace(p, i + 5, goal)) return true;
if (i > 4 && trace(p, i - 5, goal)) return true;
if (i % 5 < 4 && trace(p, i + 1, goal)) return true;
if (i % 5 > 0 && trace(p, i - 1, goal)) return true;
return false;
}
void test() {
for (int ip = 0; ip < path.length; ip++)
if (!trace(ip, path[ip][0] - 1, path[ip][1] - 1)) return;
print();
}
void enumerate(int i) {
if (i == grid.length) test();
else if (grid[i] != -1) enumerate(i + 1); // already known
else {
for (int ip = 0; ip < 5; ip++) {
grid[i] = ip;
enumerate(i + 1);
}
grid[i] = -1;
}
}
void solve() {
Arrays.fill(grid, -1);
for (int ip = 0; ip < path.length; ip++)
grid[path[ip][0] - 1] = grid[path[ip][1] - 1] = ip;
enumerate(0);
}
}
public static void main(String[] args) {
new Puzzle(new int[][]{{1, 22}, {4, 17}, {5, 18}, {9, 13}, {20, 23}}).solve();
}
}
The starting array:
[ 0, -1, -1, 1, 2]
[-1, -1, -1, 3, -1]
[-1, -1, 3, -1, -1]
[-1, 1, 2, -1, 4]
[-1, 0, 4, -1, -1]
The result:
[ 0, 1, 1, 1, 2]
[ 0, 1, 3, 3, 2]
[ 0, 1, 3, 2, 2]
[ 0, 1, 2, 2, 4]
[ 0, 0, 4, 4, 4]

Related

Algorithm: use union find to count number of islands

Suppose you need to count the number of islands on a matrix
{1, 1, 0, 0, 0},
{0, 1, 0, 0, 1},
{1, 0, 0, 1, 1},
{0, 0, 0, 0, 0},
{1, 0, 1, 0, 1}
We could simply use DFS or BFS when the input matrix size can be fitting into the memory.
However, what do we do if the input matrix is really large which could not be fitting into the memory?
I could chunk/split the input matrix into different small files and read them respectively.
But how to merge them?
I got stuck at how to merge them. I have the idea that when merging them we have to read some overlapped portion. But what is a concrete way to do so?
Trying to understand Matt's solution.
When I drew the below sample on the whiteboard and process it row by row.
Merge left then merge top and it seems won't work.
From Matt's solution.
not sure what are topidx, botidx meaning
int topidx = col * 2;
int botidx = topidx + 1;
Using union-find, the basic algorithm (without worrying about memory) is:
Create a set for every 1
Merge the sets for every pair of adjacent 1s. It doesn't matter what order you find them in, so reading order is usually fine.
Count the number of root sets -- there will be one for every island.
Easy, and with a little care, you can do this using sequential access to the matrix and only 2 rows worth of memory:
Initialize the island count to 0
Read the first row, create a set for each 1, and merge sets in adjacent columns.
For each additional row:
Read the row, create a set for each 1, and merge sets in adjacent columns;
Merge sets in the new row with adjacent sets in the previous row. ALWAYS POINT THE LINKS DOWNWARD, so that you never end up with a set in the new row linked to a parent in the old row.
Count the remaining root sets in the previous row, and add the number to your island count. These will never be able to merge with anything else.
Discard all the sets in the previous row -- you're never going to need them again, because you already counted them and nothing links to them.
Finally, count the root sets in the last row and add them to your island count.
The key to this, of course, is always pointing the links downward whenever you link sets in different rows. This will not hurt the complexity of the algorithm, and if you're using your own union-find, then it is easy to accomplish. If you're using a library data structure then you can use it just for each row, and keep track of the links between root sets in different rows yourself.
Since this is actually one of my favorite algorithms, here is an implementation in Java. This is not the most readable implementation since it involves some low-level tricks, but is super-efficient and short -- the kind of thing I'd write where performance is very important:
import java.util.Arrays;
public class Islands
{
private static final String[] matrix=new String[] {
" ############# ### ",
" # ##### ## ",
" # ## ## # # ",
" ### ## # # ",
" # ######### ## ## ",
" ## ## ",
" ########## ",
};
// find with path compression.
// If sets[s] < 0 then it is a link to ~sets[s]. Otherwise it is size of set
static int find(int[] sets, int s)
{
int parent = ~sets[s];
if (parent>=0)
{
int root = find(sets, parent);
if (root != parent)
{
sets[s] = ~root;
}
return root;
}
return s;
}
// union-by-size
// If sets[s] < 0 then it is a link to ~sets[s]. Otherwise it is size of set
static boolean union(int[] sets, int x, int y)
{
x = find(sets,x);
y = find(sets,y);
if (x!=y)
{
if ((sets[x] < sets[y]))
{
sets[y] += sets[x];
sets[x] = ~y;
}
else
{
sets[x] += sets[y];
sets[y] = ~x;
}
return true;
}
return false;
}
// Count islands in matrix
public static void main(String[] args)
{
// two rows of union-find sets.
// top row is at even indexes, bottom row is at odd indexes. This arrangemnt is chosen just
// to make resizing this array easier.
// For each value x:
// x==0 => no set. x>0 => root set of size x. x<0 => link to ~x
int cols=4;
int[] setrows= new int[cols*2];
int islandCount = 0;
for (String s : matrix)
{
System.out.println(s);
//Make sure our rows are big enough
if (s.length() > cols)
{
cols=s.length();
if (setrows.length < cols*2)
{
int newlen = Math.max(cols,setrows.length)*2;
setrows = Arrays.copyOf(setrows, newlen);
}
}
//Create sets for land in bottom row, merging left
for (int col=0; col<s.length(); ++col)
{
if (!Character.isWhitespace(s.charAt(col)))
{
int idx = col*2+1;
setrows[idx]=1; //set of size 1
if (idx>=2 && setrows[idx-2]!=0)
{
union(setrows, idx, idx-2);
}
}
}
//merge up
for (int col=0; col<cols; ++col)
{
int topidx = col*2;
int botidx = topidx+1;
if (setrows[topidx]!=0 && setrows[botidx]!=0)
{
int toproot=find(setrows,topidx);
if ((toproot&1)!=0)
{
//top set is already linked down
union(setrows, toproot, botidx);
}
else
{
//link top root down. It does not matter that we aren't counting its size, since
//we will shortly throw it aaway
setrows[toproot] = ~botidx;
}
}
}
//count root sets, discard top row, and move bottom row up while fixing links
for (int col=0; col<cols; ++col)
{
int topidx = col * 2;
int botidx = topidx + 1;
if (setrows[topidx]>0)
{
++islandCount;
}
int v = setrows[botidx];
setrows[topidx] = (v>=0 ? v : v|1); //fix up link if necessary
setrows[botidx] = 0;
}
}
//count remaining root sets in top row
for (int col=0; col<cols; ++col)
{
if (setrows[col*2]>0)
{
++islandCount;
}
}
System.out.println("\nThere are "+islandCount+" islands there");
}
}

Number flower pots in an arrangement

It's a Google interview question. There's a list of "T" and "F" only. All denotes a position such that T means position is occupied by a flower pot and F means pot is not there, so you can put another pot at this position. Find the number of pots that can be placed in a given arrangement such that no two pots are adjacent to each other(they can be adjacent in the given arrangement). If a position at the beginning is unoccupied then a pot can be placed if second position is also unoccupied and if the last position is unoccupied than a pot can be placed if second last position is also unoccupied. For ex.
TFFFTFFTFFFFT - returns 2
FFTTFFFFFTTFF - returns 4
I tried solving it by looking at adjacent values for every position with value F. Increased the counter if both adjacent positions were F and set this position as T. I need a better solution or any other solution(if any).
Let's analyse what has to be done.
So first we probably need to visit and examine each place. That suggests loop of some sort. E.g.:
for (int i = 0; i < myPlaces.Length; ++i)
When we are at a spot we have to check if it's occupied
if (place[i] == 'F')
but that's not enough to place the flower pot there. We have to check if the next and previous place is free
place[i-1]
place[i+1]
If all tree contain F you can put the flower pot there and move to next field
Now, we also have some exceptions from the rule. Beginning and end of the list. So you have to deal with them separately. E.g
if (i == 0)
{
// only check current position and next position
}
if (i == myPlaces.Length - 1) // minus 1 because indexing usually starts from 0
{
// only check current position and previous position
}
After that you can perform the checks mentioned previously.
Now let's think of the input data. Generally, it's a good habit not to modify the input data but make a copy and work on the copy. Also some data structures work better than the others for different tasks. Here you can use simple string to keep entry values. But I would say an array of chars would be a better option because then, when you find a place where you can put a flower pot you can actually replace the F with the T in an array. Then when you move to new spot your data structers knows that there is already a pot in the previous position so your algorithm won't put an adjacent one.
You would not be able to do that with string as strings are immutable and you would need to generate a new string each time.
Note that it's only a naive algorithm with a lot of scope for improvement and optimization. But my goal was rather to give some idea how to approach this kind of problems in general. I'll leave implementing of the details to you as an afternoon exercise before targeting a job at Google.
You may be able to do this with a modified Mergesort. Consider the flowerpots that can be placed in the singletons, then the flowerpots that can be placed in the doubleton merges of those singletons, up the tree to the full arrangement. It would complete in O(n lg n) for a list of n flowerpots.
There is certainly a way to do this with a modified Rod Cutting algorithm with complexity O(n^2). The subproblem is whether or not an open "false set" exists in the substring being considered. The "closed false sets" already have some maximum value computed for them. So, when a new character is added, it either increases the amount of flowerpots that can be inserted, or "locks in" the maximum quantity of available flowerpots for the substring.
Also, you know that the maximum flowerpots that can be placed in a set of n open positions bound by closed positions is n - 2 (else n-1 if only bracketed on one side, i.e. the string begins or ends with a "false set". The base condition (the first position is open, or the first position is closed) can calculated upon reaching the second flowerpot.
So, we can build up to the total number of flowerpots that can be inserted into the whole arrangement in terms of the maximum number of flowerpots that can be inserted into smaller subarrangements that have been previously calculated. By storing our previous calculations in an array, we reduce the amount of time necessary to calculate the maximum for the next subarrangement to a single array lookup and some constant-time calculations. This is the essence of dynamic programming!
EDIT: I updated the answer to provide a description of the Dynamic Programming approach. Please consider working through the interactive textbook I mentioned in the comments! http://interactivepython.org/runestone/static/pythonds/index.html
I would approach the problem like this. You need FFF to have one more pot, FFFFF for two pots, etc. To handle the end cases, add an F at each end.
Because this is very similar to a 16-bit integer, the algorithm should use tricks like binary arithmetic operations.
Here is an implementation in Python that uses bit masking (value & 1), bit shifting (value >>= 1) and math ((zeros - 1) / 2) to count empty slots and calculate how many flower pots could fit.
#value = 0b1000100100001
value = 0b0011000001100
width = 13
print bin(value)
pots = 0 # number of flower pots possible
zeros = 1 # number of zero bits in a row, start with one leading zero
for i in range(width):
if value & 1: # bit is one, count the number of zeros
if zeros > 0:
pots += (zeros - 1) / 2
zeros = 0
else: # bit is zero, increment the number found
zeros += 1
value >>= 1 # shift the bits to the right
zeros += 1 # add one trailing zero
pots += (zeros - 1) / 2
print pots, "flower pots"
The solution is really simple, check the previous and current value of the position and mark the position as plantable (or puttable) and increment the count. Read the next value, if it is already is planted, (backtrack and) change the previous value and decrement the count. The complexity is O(n). What we really want to check is the occurrence of 1001. Following is the implementation of the algorithm in Java.
public boolean canPlaceFlowers(List<Boolean> flowerbed, int numberToPlace) {
Boolean previous = false;
boolean puttable = false;
boolean prevChanged = false;
int planted = 0;
for (Boolean current : flowerbed) {
if (previous == false && current == false) {
puttable = true;
}
if (prevChanged == true && current == true) {
planted--;
}
if (puttable) {
previous = true;
prevChanged = true;
planted++;
puttable = false;
} else {
previous = current;
prevChanged = false;
}
}
if (planted >= numberToPlace) {
return true;
}
return false;
}
private static void canPlaceOneFlower(List<Boolean> flowerbed, FlowerBed fb) {
boolean result;
result = fb.canPlaceFlowers(flowerbed, 1);
System.out.println("Can place 1 flower");
if (result) {
System.out.println("-->Yes");
} else {
System.out.println("-->No");
}
}
private static void canPlaceTwoFlowers(List<Boolean> flowerbed, FlowerBed fb) {
boolean result;
result = fb.canPlaceFlowers(flowerbed, 2);
System.out.println("Can place 2 flowers");
if (result) {
System.out.println("-->Yes");
} else {
System.out.println("-->No");
}
}
private static void canPlaceThreeFlowers(List<Boolean> flowerbed, FlowerBed fb) {
boolean result;
result = fb.canPlaceFlowers(flowerbed, 3);
System.out.println("Can place 3 flowers");
if (result) {
System.out.println("-->Yes");
} else {
System.out.println("-->No");
}
}
private static void canPlaceFourFlowers(List<Boolean> flowerbed, FlowerBed fb) {
boolean result;
result = fb.canPlaceFlowers(flowerbed, 4);
System.out.println("Can place 4 flowers");
if (result) {
System.out.println("-->Yes");
} else {
System.out.println("-->No");
}
}
public static void main(String[] args) {
List<Boolean> flowerbed = makeBed(new int[] { 0, 0, 0, 0, 0, 0, 0 });
FlowerBed fb = new FlowerBed();
canPlaceFourFlowers(flowerbed, fb);
canPlaceThreeFlowers(flowerbed, fb);
flowerbed = makeBed(new int[] { 0, 0, 0, 1, 0, 0, 0 });
canPlaceFourFlowers(flowerbed, fb);
canPlaceThreeFlowers(flowerbed, fb);
canPlaceTwoFlowers(flowerbed, fb);
flowerbed = makeBed(new int[] { 1, 0, 0, 1, 0, 0, 0, 1 });
canPlaceFourFlowers(flowerbed, fb);
canPlaceThreeFlowers(flowerbed, fb);
canPlaceTwoFlowers(flowerbed, fb);
canPlaceOneFlower(flowerbed, fb);
}
My solution using dynamic programming.
ar is array in the form of ['F','T','F'].
import numpy as np
def pot(ar):
s = len(ar)
rt = np.zeros((s,s))
for k in range(0,s):
for i in range(s-k):
for j in range(i,i+k+1):
left = 0
right = 0
if ar[j] != 'F':
continue
if j-1 >= i and ar[j-1] == 'T':
continue
else:
left = 0
if j+1 <= i+k and ar[j+1] == 'T':
continue
else:
right = 0
if j-2 >= i:
left = rt[i][j-2]
if j+2 <= i+k:
right = rt[j+2][i+k]
rt[i][i+k] = max(rt[i][i+k], left+right+1)
return rt[0][len(ar)-1]
My solution written in C#
private static int CheckAvailableSlots(string str)
{
int counter = 0;
char[] chrs = str.ToCharArray();
if (chrs.FirstOrDefault().Equals('F'))
if (chrs.Length == 1)
counter++;
else if (chrs.Skip(1).FirstOrDefault().Equals('F'))
counter++;
if (chrs.LastOrDefault().Equals('F') && chrs.Reverse().Skip(1).FirstOrDefault().Equals('F'))
counter++;
for (int i = 1; i < chrs.Length - 2; i++)
{
if (chrs[i - 1].Equals('T'))
continue;
else if (chrs[i].Equals('F') && chrs[i + 1].Equals('F'))
{
chrs[i] = 'T';
counter++;
i++;
}
else
i++;
}
return counter;
}
// 1='T'
// 0='F'
int[] flowerbed = new int[] {1,0,0,0,0,1};
public boolean canPlaceFlowers(int[] flowerbed, int n) {
int tg = 0;
for (int i = 0, g = 1; i < flowerbed.length && tg < n; i++) {
g += flowerbed[i] == 0 ? flowerbed.length - 1 == i ? 2 : 1 : 0;
if (flowerbed[i] == 1 || i == flowerbed.length - 1) {
tg += g / 2 - (g % 2 == 0 ? 1 : 0);
g = 0;
}
}
return tg >= n;
}
Most of these answers (unless they alter the array or traverse and a copy) dont consider the situation where the first 3 (or last 3) pots are empty. These solutions will incorrectly determine that FFFT will contain 2 spaces, rather than just one. We therefore need to start at the third element (rather than then second) and end at index length - 3 (rather than length - 2). Also, while looping through the array, if an eligible index is found, the index just be incremented by 2, otherwise TTFFFFT would give 2 available plots instead of one. This is true unless you alter the array while looping or use a copy of the array and alter it.
Edit: this holds true unless the question is how many spaces are available for planting, rather than how many total plants can be added

how to save shortest path in dijkstra algorithm

So first let's define Dijkstra algorithm:
Dijkstra's algorithm finds single-source shortest paths in a directed graph with non-negative edge weights.
I want to know how can I save the shortest path form s to t with Dijkstra algorithm.
I searched on google, but I couldn't find anything particular; I also changed Dijkstra algorithm, but I could't get any answer. How can I save the shortest path from s to t with Dijkstra?
I know my question is basic and unprofessional, but any help would be appreciated. Thanks for considering my question.
If you look at the pseudocode from the Wikipedia link you gave, you'll see an array in there called prev[]. This array contains, for each node v in the graph, the previous node u in the shortest path between the source node s and v. (This array is also called the predecessor or parent array.)
In other words, the shortest path between s and v is:
s -> u -> v
where u = prev[v]
The path from s to u might have several nodes in between, so to reconstruct the path from s to v, you just walk back along the path defined by the prev[] array using the code snippet below the main pseudocode (target is v):
1 S ← empty sequence
2 u ← target
3 while prev[u] is defined: // Construct the shortest path with a stack S
4 insert u at the beginning of S // Push the vertex onto the stack
5 u ← prev[u] // Traverse from target to source
6 end while
One extremely short way to do so is to use recursion and a "parent array."
If you initialize all of the points' parents to -1, and then as you complete dijkstra's, update the parent array, you are able to recurse back from any point till you get to the source and print out the path. Here is a very short and easy to understand recursion snippet:
// Function to print shortest path from source to j using parent array
void path(parent array, int j)
{
    // Base Case : If j is source
    if (jth element of parent is -1) return;
 
    path(parent, jth element of parent);
  print j;
}
Note that instead of printing "j" out, you can store it in a global vector (or other datatype for languages that are not C-related) for later use.
just a modify form there
# define INF 0x3f3f3f3f
// iPair ==> Integer Pair
typedef pair<int, int> iPair;
void addEdge(vector <pair<int, int> > adj[], int u, int v, int wt)
{
adj[u].push_back(make_pair(v, wt));
adj[v].push_back(make_pair(u, wt));
}
void shortestPath(vector<pair<int, int> > adj[], int V, int src, int target)
{
priority_queue< iPair, vector <iPair>, greater<iPair> > pq;
vector<int> dist(V, INF);
vector<bool> visited(V, false);
vector<int> prev(V, -1);
pq.push(make_pair(0, src));
dist[src] = 0;
while (!pq.empty() && !visited[target])
{
int u = pq.top().second;
pq.pop();
if (visited[u]) {
continue;
}
visited[u] = true;
for (auto x : adj[u])
{
int v = x.first;
int weight = x.second;
if (dist[v] > dist[u] + weight)
{
//relax
dist[v] = dist[u] + weight;
pq.push(make_pair(dist[v], v));
prev[v] = u;
}
}
}
vector<int> res;
res.push_back(target);
int temp = target;
while (temp != 0)
{
temp = prev[temp];
res.push_back(temp);
}
//cout << res;
}
int main()
{
const int V = 9;
vector<iPair > adj[V];
addEdge(adj, 0, 1, 4);
addEdge(adj, 0, 7, 8);
addEdge(adj, 1, 2, 8);
addEdge(adj, 1, 7, 11);
addEdge(adj, 2, 3, 7);
addEdge(adj, 2, 8, 2);
addEdge(adj, 2, 5, 4);
addEdge(adj, 3, 4, 9);
addEdge(adj, 3, 5, 14);
addEdge(adj, 4, 5, 10);
addEdge(adj, 5, 6, 2);
addEdge(adj, 6, 7, 1);
addEdge(adj, 6, 8, 6);
addEdge(adj, 7, 8, 7);
shortestPath(adj, V, 0, 6); //the last one means target
return 0;
}
Most libraries that use this algorithm will likely give you a way to do this. But in general just keep track of the path to each node. Ie give each node an attrribute shortestPathToNode in which you store the list of nodes

using binary search to count occurrences

assume I have sorted array A in length n so 1
I need to write pseuodocode of a program that give output of all occurrences of each element.
the algorithm runtime has to be maximum k(c1+c2*log(n)).
example - A=[1,1,2,2,2,5,5,5,5] ----> (1,2)(2,3)(5,4)
I thought about using binary search when the first element I want to count is A[1] and I need to find his last occurrence.
then the next element is A[last occurrence index + 1] and so on.
I have a bit difficult with the idea and writig it down as pseuodocode.
tnx
Recursive algorithm, it gets left and right position and calculates middle position. Going deeper if there is number change, en edge. Up to here it is simple binary search. But once it detects (on distance=1) an edge, change of numbers, it will return it in 4 values: 'what number sequence ended', 'on what position', 'what started', 'on what position'. Parent node then merges these 4 values from left and right side and if it detects complete sequence 'in the middle', it immediately prints it and pass just ending edge (from left side) and starting edge (from right).
It is not possible to achieve that asymptotic complexity.
The reason is no matter what algorithm it is, When all the n elements are distinct, It has to return all the elements.That implies it has to read all of them.Of course, this operation takes O(n).
You can count number of occurrences for one entry in O(log(n))
static int count(int[] array, int target, int start, int end, Func<int, int, bool> compare)
{
if (end < start) { return start; }
int m = (start + end) / 2;
if (compare(target, array[m])) { return count(array, target, start, m - 1, compare); }
else { return count(array, target, m + 1, end, compare); }
}
static void Main(string[] args)
{
int[] a = { 1, 3, 8, 12, 12, 12, 25, 88 };
int r1 = count(a, 12, 0, a.Length - 1, (x1, x2) =>
{
return x1 < x2;
});
int r2 = count(a, 12, 0, a.Length - 1, (x1, x2) =>
{
return x1 <= x2;
});
Console.Out.WriteLine("count=" + (r1 - r2).ToString());
}

Find Second largest number in array at most n+log₂(n)−2 comparisons [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
The community reviewed whether to reopen this question 12 months ago and left it closed:
Original close reason(s) were not resolved
Improve this question
You are given as input an unsorted array of n distinct numbers, where n is a power of 2. Give an algorithm that identifies the second-largest number in the array, and that uses at most n+log₂(n)−2 comparisons.
Start with comparing elements of the n element array in odd and even positions and determining largest element of each pair. This step requires n/2 comparisons. Now you've got only n/2 elements. Continue pairwise comparisons to get n/4, n/8, ... elements. Stop when the largest element is found. This step requires a total of n/2 + n/4 + n/8 + ... + 1 = n-1 comparisons.
During previous step, the largest element was immediately compared with log₂(n) other elements. You can determine the largest of these elements in log₂(n)-1 comparisons. That would be the second-largest number in the array.
Example: array of 8 numbers [10,9,5,4,11,100,120,110].
Comparisons on level 1: [10,9] ->10 [5,4]-> 5, [11,100]->100 , [120,110]-->120.
Comparisons on level 2: [10,5] ->10 [100,120]->120.
Comparisons on level 3: [10,120]->120.
Maximum is 120. It was immediately compared with: 10 (on level 3), 100 (on level 2), 110 (on level 1).
Step 2 should find the maximum of 10, 100, and 110. Which is 110. That's the second largest element.
sly s's answer is derived from this paper, but he didn't explain the algorithm, which means someone stumbling across this question has to read the whole paper, and his code isn't very sleek as well. I'll give the crux of the algorithm from the aforementioned paper, complete with complexity analysis, and also provide a Scala implementation, just because that's the language I chose while working on these problems.
Basically, we do two passes:
Find the max, and keep track of which elements the max was compared to.
Find the max among the elements the max was compared to; the result is the second largest element.
In the picture above, 12 is the largest number in the array, and was compared to 3, 1, 11, and 10 in the first pass. In the second pass, we find the largest among {3, 1, 11, 10}, which is 11, which is the second largest number in the original array.
Time Complexity:
All elements must be looked at, therefore, n - 1 comparisons for pass 1.
Since we divide the problem into two halves each time, there are at most log₂n recursive calls, for each of which, the comparisons sequence grows by at most one; the size of the comparisons sequence is thus at most log₂n, therefore, log₂n - 1 comparisons for pass 2.
Total number of comparisons <= (n - 1) + (log₂n - 1) = n + log₂n - 2
def second_largest(nums: Sequence[int]) -> int:
def _max(lo: int, hi: int, seq: Sequence[int]) -> Tuple[int, MutableSequence[int]]:
if lo >= hi:
return seq[lo], []
mid = lo + (hi - lo) // 2
x, a = _max(lo, mid, seq)
y, b = _max(mid + 1, hi, seq)
if x > y:
a.append(y)
return x, a
b.append(x)
return y, b
comparisons = _max(0, len(nums) - 1, nums)[1]
return _max(0, len(comparisons) - 1, comparisons)[0]
The first run for the given example is as follows:
lo=0, hi=1, mid=0, x=10, a=[], y=4, b=[]
lo=0, hi=2, mid=1, x=10, a=[4], y=5, b=[]
lo=3, hi=4, mid=3, x=8, a=[], y=7, b=[]
lo=3, hi=5, mid=4, x=8, a=[7], y=2, b=[]
lo=0, hi=5, mid=2, x=10, a=[4, 5], y=8, b=[7, 2]
lo=6, hi=7, mid=6, x=12, a=[], y=3, b=[]
lo=6, hi=8, mid=7, x=12, a=[3], y=1, b=[]
lo=9, hi=10, mid=9, x=6, a=[], y=9, b=[]
lo=9, hi=11, mid=10, x=9, a=[6], y=11, b=[]
lo=6, hi=11, mid=8, x=12, a=[3, 1], y=11, b=[9]
lo=0, hi=11, mid=5, x=10, a=[4, 5, 8], y=12, b=[3, 1, 11]
Things to note:
There are exactly n - 1=11 comparisons for n=12.
From the last line, y=12 wins over x=10, and the next pass starts with the sequence [3, 1, 11, 10], which has log₂(12)=3.58 ~ 4 elements, and will require 3 comparisons to find the maximum.
I have implemented this algorithm in Java answered by #Evgeny Kluev. The total comparisons are n+log2(n)−2. There is also a good reference:
Alexander Dekhtyar: CSC 349: Design and Analyis of Algorithms. This is similar to the top voted algorithm.
public class op1 {
private static int findSecondRecursive(int n, int[] A){
int[] firstCompared = findMaxTournament(0, n-1, A); //n-1 comparisons;
int[] secondCompared = findMaxTournament(2, firstCompared[0]-1, firstCompared); //log2(n)-1 comparisons.
//Total comparisons: n+log2(n)-2;
return secondCompared[1];
}
private static int[] findMaxTournament(int low, int high, int[] A){
if(low == high){
int[] compared = new int[2];
compared[0] = 2;
compared[1] = A[low];
return compared;
}
int[] compared1 = findMaxTournament(low, (low+high)/2, A);
int[] compared2 = findMaxTournament((low+high)/2+1, high, A);
if(compared1[1] > compared2[1]){
int k = compared1[0] + 1;
int[] newcompared1 = new int[k];
System.arraycopy(compared1, 0, newcompared1, 0, compared1[0]);
newcompared1[0] = k;
newcompared1[k-1] = compared2[1];
return newcompared1;
}
int k = compared2[0] + 1;
int[] newcompared2 = new int[k];
System.arraycopy(compared2, 0, newcompared2, 0, compared2[0]);
newcompared2[0] = k;
newcompared2[k-1] = compared1[1];
return newcompared2;
}
private static void printarray(int[] a){
for(int i:a){
System.out.print(i + " ");
}
System.out.println();
}
public static void main(String[] args) {
//Demo.
System.out.println("Origial array: ");
int[] A = {10,4,5,8,7,2,12,3,1,6,9,11};
printarray(A);
int secondMax = findSecondRecursive(A.length,A);
Arrays.sort(A);
System.out.println("Sorted array(for check use): ");
printarray(A);
System.out.println("Second largest number in A: " + secondMax);
}
}
the problem is:
let's say, in comparison level 1, the algorithm need to be remember all the array element because largest is not yet known, then, second, finally, third. by keep tracking these element via assignment will invoke additional value assignment and later when the largest is known, you need also consider the tracking back. As the result, it will not be significantly faster than simple 2N-2 Comparison algorithm. Moreover, because the code is more complicated, you need also think about potential debugging time.
eg: in PHP, RUNNING time for comparison vs value assignment roughly is :Comparison: (11-19) to value assignment: 16.
I shall give some examples for better understanding. :
example 1 :
>12 56 98 12 76 34 97 23
>>(12 56) (98 12) (76 34) (97 23)
>>> 56 98 76 97
>>>> (56 98) (76 97)
>>>>> 98 97
>>>>>> 98
The largest element is 98
Now compare with lost ones of the largest element 98. 97 will be the second largest.
nlogn implementation
public class Test {
public static void main(String...args){
int arr[] = new int[]{1,2,2,3,3,4,9,5, 100 , 101, 1, 2, 1000, 102, 2,2,2};
System.out.println(getMax(arr, 0, 16));
}
public static Holder getMax(int[] arr, int start, int end){
if (start == end)
return new Holder(arr[start], Integer.MIN_VALUE);
else {
int mid = ( start + end ) / 2;
Holder l = getMax(arr, start, mid);
Holder r = getMax(arr, mid + 1, end);
if (l.compareTo(r) > 0 )
return new Holder(l.high(), r.high() > l.low() ? r.high() : l.low());
else
return new Holder(r.high(), l.high() > r.low() ? l.high(): r.low());
}
}
static class Holder implements Comparable<Holder> {
private int low, high;
public Holder(int r, int l){low = l; high = r;}
public String toString(){
return String.format("Max: %d, SecMax: %d", high, low);
}
public int compareTo(Holder data){
if (high == data.high)
return 0;
if (high > data.high)
return 1;
else
return -1;
}
public int high(){
return high;
}
public int low(){
return low;
}
}
}
Why not to use this hashing algorithm for given array[n]? It runs c*n, where c is constant time for check and hash. And it does n comparisons.
int first = 0;
int second = 0;
for(int i = 0; i < n; i++) {
if(array[i] > first) {
second = first;
first = array[i];
}
}
Or am I just do not understand the question...
In Python2.7: The following code works at O(nlog log n) for the extra sort. Any optimizations?
def secondLargest(testList):
secondList = []
# Iterate through the list
while(len(testList) > 1):
left = testList[0::2]
right = testList[1::2]
if (len(testList) % 2 == 1):
right.append(0)
myzip = zip(left,right)
mymax = [ max(list(val)) for val in myzip ]
myzip.sort()
secondMax = [x for x in myzip[-1] if x != max(mymax)][0]
if (secondMax != 0 ):
secondList.append(secondMax)
testList = mymax
return max(secondList)
public static int FindSecondLargest(int[] input)
{
Dictionary<int, List<int>> dictWinnerLoser = new Dictionary<int, List<int>>();//Keeps track of loosers with winners
List<int> lstWinners = null;
List<int> lstLoosers = null;
int winner = 0;
int looser = 0;
while (input.Count() > 1)//Runs till we get max in the array
{
lstWinners = new List<int>();//Keeps track of winners of each run, as we have to run with winners of each run till we get one winner
for (int i = 0; i < input.Count() - 1; i += 2)
{
if (input[i] > input[i + 1])
{
winner = input[i];
looser = input[i + 1];
}
else
{
winner = input[i + 1];
looser = input[i];
}
lstWinners.Add(winner);
if (!dictWinnerLoser.ContainsKey(winner))
{
lstLoosers = new List<int>();
lstLoosers.Add(looser);
dictWinnerLoser.Add(winner, lstLoosers);
}
else
{
lstLoosers = dictWinnerLoser[winner];
lstLoosers.Add(looser);
dictWinnerLoser[winner] = lstLoosers;
}
}
input = lstWinners.ToArray();//run the loop again with winners
}
List<int> loosersOfWinner = dictWinnerLoser[input[0]];//Gives all the elemetns who lost to max element of array, input array now has only one element which is actually the max of the array
winner = 0;
for (int i = 0; i < loosersOfWinner.Count(); i++)//Now max in the lossers of winner will give second largest
{
if (winner < loosersOfWinner[i])
{
winner = loosersOfWinner[i];
}
}
return winner;
}

Resources