First of all this is an assingment and I am not looking for direct answers but instead the complexity of the best solution as you might be thinking it .
This is the known problem of shortest path between 2 points in a matrix (Start and End) while having obstacles in the way. Moves acceptables is up,down,left and right . Lets say when moving i carry sth and the cost of each movement is 2 . There are points in the matrix (lets name them B points) where I can leave this sth in one B point and pick it up from another B point . Cost of dumping sth in B point is 1 and cost of picking sth up from a B point is 1 again . Whenever I move without this sth , my cost of moving now is 1 .
What I think of the solution is transform the matrix into a tree and have a BFS applied . However that works without the B points .
Whenever i take into account the B points complexity comes to a worst case scenario N^2.
Here is an example :
S - - -
- - - -
B - - B
- - O E
S = Start , E = End , B = B point to drop sth, O = obstacle
So i start with S move down down to the B point (2*2=4 points) leave sth in the B point (1 point ) move right right (2*1= 2 points ) , pick it up (1 point ) , move down 2 points = total of 10 points .
What i thought was build the tree with nodes every B point , however this would create a very dense cyclic graph of almost (V-1)*(V-1) edges which takes the algortithm in N^2 boundaries just to create the graph .
That is the worst case scenario as above :
S b b b
b b b b
b b b b
b b b E
Another option I thought was that of first calculating shortest paths withouth B points .
Then have iterations where at each iteration :
First have bfs on S and closest B
have BFS on E and closest B
Then see if there is a path between B of closest to S and B closest to E .
If there is then I would see if the path is smaller than that of regular shortest path with obstacles .
If that is bigger then there is no shortest path (no greedy test).
If there is no path between the 2 B points , try second closest to S and try again .
If no path again , the second closest to E and closest to S .
However I am not able to calculate the complexity in this one in the worst case scenario plus there is no greedy test that evaluates that.
Any help on calculating the complexity or even pointing out the best complexity solution (not the solution but just the complexity ) would be greatly appreciated
Your matrix is a representation of a graph. Without the cheat paths it is quite easy to implement a nice BFS. Implementing the cheat paths is not a big deal. Just add the same matrix as another 'layer' on top of the first one. bottom layer is 'carry', top layer is 'no carry'. You can move to the other layer only at B-points for the given cost. This is the same BFS with a third dimension.
You have n^2 nodes and (n-1)^2 edges per layer and additionally a maximum of n^2 eges connecting the layers. That's O(n^2).
You can just build a new graph with nodes labeled by (N, w) where N is a node in the original graph (so a position in your matrix), and w=0 or 1 is whether you're carrying a weight. It's then quite easy to add all possible edges in this graph
This new graph is of size 2*V, not V^2 (and the number of edges is around 4*V+number(B)).
Then you can use a shortest path algorithm, for instance Dijkstra's algorithm: complexity O(E + V log(V)) which is O(V log(V)) in your case.
Related
Given a simple polygon P, consisting of n vertices, and Set S Of k points, determine if each of the polygon vertices are covered by some point from S.
My best solution was to check for every P vertex if there exist such point in S - total complexity of O(n*k). I belive there should be a more efficient solution. any hints?
Whether P is a polygon or not seems to be irrelevant. So the generalized question becomes: Given 2 sets of points A (with a points) and B (with b points), find out whether A is a subset of B or not?
The simple solution is O(a * b) but you can also get O(a + b) by doing some preprocessing.
Put all the points of B in a hash map with the x-coordinate as key and a hash set with the y-coordinates as values (Map<Number,Set<Number>>). This lets you query whether a point (x, y) is in B in O(1): map.containsKey(x) && map.get(x).contains(y).
Go through all the points of A and check whether the point is in B using the datastructure created above.
Step 1 is O(b) and Step 2 is O(a) which gives O(a + b).
Here I use a pseudocode to present my algorithm,it's a variation of DFS
The coding style is imitating the Introduction to Algorithm ,Everytime we come across a vertex,its color is painted BLACK .Suppose the starting vertex is START,and the target vertex is TARGET,and the graph is represented as G=(V,E).One more thing,assume that the graph is connected,and strongly connected if it's a directed graph.
FIND-ALL-PATH(G,START,END)
for each vertex u in G.V
u.color=WHITE
path=0//store the result
DFS-VISIT(G,START)
DFS-VISIT(G,u)
if(u==TARGET)
path=path+1
return
u.color=BLACK
for each v in G:Adj[u]
if(v.color==WHITE)
DFS-VISIT(G,v)
u.color=WHITE;//re-paint the vertex to find other possible ways
How to analyze the Time Complexity of the algorithm above?If it's the normal DFS then of course its O(N+E),because each vertex is visited only once,and each edge is visited twice.But what about this?It seems hard to specify the time that each vertex or edge is visited.
To analyze the time complexity for FIND-ALL-PATH, let's see what is the time complexity of DFS-VISIT. I am assuming you are using Adjacency List for representing the Graph.
Here, in one call of DFS-VISIT every vertex which is connected to u (the vertex you passed as the argument) is going to be explored once (i.e. vertex color is going to be changed to BLACK). Since this is a recursive function so in each recursion a new stack is going to be formed and there the set G:Adj[u] present in each stack is nothing but element adjacent to u. Therefore, every node in all the list put together will be examined(color is changed) exactly once and whenever they are examined, we do a constant work (i.e. O(1) operation). There are overall E elements in case of directed Graph and 2E in case of un-directed Graph in Adjacency List representation. So we say it's time is O(E), where E is the number of edges. In some books, they add extra time O(N), where N is the number of vertices, so they say they overall time complexity for DFS-VISIT is O(N+E)(I think that the reason for that extra O(N) time is the for loop which gets executed N number of times or it may be something else). BTW, N is always less than E so you can either ignore it or consider it, it doesn't affect the Asymptotic time for the DFS-VISIT.
The time complexity of the function FIND-ALL-PATH is N * time complexity for DFS-VISIT; where N is the number of vertices in the Graph. So I would say that the algorithm you wrote above is not exactly same as depth-first traversal algorithm but then it will do the same work as depth-first traversal. The time taken in your algorithms is more because you are calling DFS-VISIT for each vertex in your graph. Your function FIND-ALL-PATH could be optimized in a way that before calling DFS-VISIT function just check if the color of the vertex is changed to BLACK or not (that's what is generally done in depth-first traversal).
i.e. you should have written the function like this:
FIND-ALL-PATH(G,START,END)
for each vertex u in G.V
u.color=WHITE
path=0//store the result
for each vertex u in G.V
if u.color is WHITE
DFS-VISIT(G,START)
Now this function written above will have same time complexity as DFS-VISIT.
Also note that there is some time taken to initialize the color of all vertices to WHITE, which is O(N) operation.
So, the overall time complexity of your function FIND-ALL-PATH is O(N)+O(N*(N+E)) or you can ignore the first O(N) (as it's very less as compared to the other term).
Thus, time complexity = O(N*(N+E)), or if you assume just O(E) time for your DFS-VISIT function then you can say that time complexity is O(N*E).
Let me know if you have doubt at any point mentioned above.
For directed graph :-
Suppose there are 7 vertices {0,1,2,3,4,5,6} and consider the worst case where every vertex is connected to every other vertex =>
No of edges required to reach from x to y vertices is as follows :
(6->6) 6 to 6 =0
(5->6) 5 to 6 =1
(4->6) 4 to 6 = (4 to 5 -> 6) + (4 to 6->6) = (1+( 5 -> 6)) + (1+0) =(1 + 1) + 1= 3
(3->6) 3 to 6 =(3 to 4 -> 6) + (3 to 5 -> 6 ) + (3 to 6->6) = (1+3) + (1+1) + (1+0)=7
(2->6) 2 to 6= 4+7+3+1=15
(1->6) 1 to 6= 5+15+7+3+1=31
(0->6) 0 to 6 = 6+5+15+7+3+1=63
So the time complexity to cover all the path to reach from 0 to 6= summation of (1+3+7+15+.....+T(n-1)+T(n))+(Total no of vertices -1) = (2^(n+1)-2-n)+(V-1)
value of n=V-1.
So final time complexity = O(2^V)
For undirected graph :-
Every edge will be traversed twice = 2*((2^(n+1)-2-n)+(V-1))=O(2^(V+1))
We have a set of nodes which are connected in a circle, with one additional one-way connection from one node to another. The set of instructions is composed of F, going one node clockwise, B going one node counter-clockwise, and P, going through the one-way connection.
Each node has a one-way connection to a node (which can be itself). Each connection can go on the same node than the connection of the node before it, or further (the nodes and the ones on the other side of the connections are in the same order). I need to find the length of the shortest instruction set which can move to the first node, no matter the starting node.
I have already tried looking for chains of connections ending in a node which connects to itself, since it is where everything should converge, but after that first convergence I haven't found any optimized way of determining the shortest path to the next "best" convergence. I didn't find anything about this on the internet and I'm running short of ideas. I think there's a mathematical theorem behind this but I can't find any.
I have already looked at Minimum Spanning Trees (Find the minimal common path from any nodes to one node), but those doesn't fit since I have a set of instructions.
EDIT : An example.
Suppose that we have the following data : 0 1 0 0 (that means that the connection of the first node goes 0 nodes forward, the second one goes 1 node forward, etc.). This can be drawn that way (I'm omitting the links between each node) :
o--o
| | <------------ Those are "dead" nodes
| V
o--1 2
|
V <--- This is a "convergence chain"
o--4 3--o
| ^ ^ |
| | | |
o--o o--o
Here, the solution is PBPBPFF (or PBPBPBB). Here we are using the convergence chain as a mean to group them, and then we shift them to the first node.
Let's assume that the length of the circle is N. On the input, we've also got an array C[N].
There are three possible operations for a position P:
a) p = (p - 1) % N
b) p = (p + 1) % N
c) p = (p + C[p]) % N
Let's try try decompose the problem a bit. First, let's try to find a chain that takes positions P, Q to the same position R.
We'll soon find out that getting the two positions "closer" to each other won't take more than O(N) steps. If we perform N steps and the two positions are still at the same distance, we should rather use simple rotation, which would take at most N/2 steps.
From this observation, if it's possible, a simple BFS finds a solution in O(N^2). If the solution isn't found in N^2 steps, the solution doesn't exist. Now, using this chain, move all input positions, pick another two and find a solution for them. In the end, we end up with a single position, converting of which to the initial position is trivial. So if there's any solution to the problem, this algorithm will find it at
O(
N - n positions
*
(N^2 - merge two positions to one
+
N * N^2 - recalculate the positions with chain we've just found
)
)
, which is at most N^3 commands (each applied N times).
Now, we can simply BFS a graph of all possible combinations.
Starting with ("", [0..n]), we can loop through the queue and push new three items according to our commands (if the positions weren't find yet) :
(commands, [p1, p2, ... pn]) ->
(commands + "F", [(p1 + 1) % N, ... (pn + 1) % N])
(commands + "B", [(p1 - 1) % N, ... (pn - 1) % N])
(commands + "P", [(p1 + C[p1]) % N, ... (pn + C[pn]) % N])
We terminate either when the vector is filled with zeros or if we've performed enough steps so that a solution cannot be found. The boundaries could be possibly improved, but it should be clear that these I've mentioned work.
In an undirected random graph of 8 vertices, the probability of an edge being present between a pair of vertices in 1/2. What is the expected number of unordered cycles of length 3?
Here's how I thought of going about it:
Method 1
Basically cycles ("unordered" i am assuming to mean that the vertices can be taken in any order) of length 3 would be triangles.
Letting number of vertices = v, and no of such cycles being C
For n=3, C = 1
For n = 4, c = 4. (a square with 2 diagonal lines. 4 unique triangles).
....
For n>3, C(n) = (n-2) + (n-2)(n-3) + (n-4), generalizing.
This is because: let us start with an outside edge, and the triangles possible with that as a base. For the first edge we choose (2 vertices gone there), there are (n-2) other vertices to choose the 3rd point of triangle. So (n-2) in the first term.
Next, the last term is because the very last side we choose to base our triangles on would have its leftmost and rightmost triangles taken already by the first side we chose and its immediate predecessor.
The middle term is the product of the remaining number of edges and possible triangles.
.--------.
. .
. .
. .
With the above set of 8 vertices one can trivially think it out visually. (If better diagrams are needed, I shall do the needful!). So for v=8, C(8) = 40. So, as probability of an edge is 1/2 . . .
Method 2 The number of triangles from n points is nC3, where C is "combination". But as half of these edges are not expected to exist . . .
I am not sure how to proceed beyond this point. Any hints in the right direction would be great. Btw its not a homework question.
You have nC3 possible triangles. For a triangle to appear all three edges must exist - so the probability of a specific triangle to appear is 1/8.
The expected number of triangles is then (nC3) / 8.
In your case, 8C3 / 8 or 7.
So we have a graph with 8 vertices, now we want all three length cycles possible, given that probability of having an edge between any two vertices =1/2.
Suppose a b and c are any three vertices of given graph, now to make a cycle between a, b and c there should be an edge between a------b(probability of this=1/2) and there should be an edge between b------c(probability of this=1/2) and there should be an edge between c------a(probability of this=1/2) ,
So probability of getting one cycle = (1/2)(1/2)(1/2)*1 =1/8
And probability of getting all cycles=
1/8 *(total no of 3 length cycles possible with 8 vertices)
= 1/8*(8C3) =7.
so you have given n vertices now you are having nC1 way to select the first edge.
probability of existing that edge would be 1/2 .now in the left n-1 edge we can choose (n-1)C1 ways with probability as 1/2 similarly third edge with (n-2)C1 with probability 1/2 so simultaneously this can done as {nC1*(1/2)(n-1)C1(1/2)*(n-2)C1*1/2}/3!
we have to divide by 3!due to fact that it is asking for unordered.
I am thinking about the algorithm for the following problem (found on carrercup):
Given a polygon with N vertexes and N edges. There is an int number(could be negative) on every vertex and an operation in set(*,+) on every edge. Every time, we remove an edge E from the polygon, merge the two vertexes linked by the edge(V1,V2) to a new vertex with value: V1 op(E) V2. The last case would be two vertexes with two edges, the result is the bigger one.
Return the max result value can be gotten from a given polygon.
I think we can use just greedy approach. I.e. for polygon with k edges find a pair (p, q) which produces the maximum number when collapsing: (p ,q) = max ({i operation j : i, j - adjacent edges)
Then just call a recursion on polygons:
1. Let function CollapseMaxPair( P(k) ) - gets polygon with k edges and returns 'collapsed' polygon with k-1 edges
2. Then our recursion:
P = P(N);
Releat until two edges left
P = CollapseMaxPair( P )
maxvalue = max ( two remained values)
What do you think?
I have answered this question here: Google Interview : Find the maximum sum of a polygon and it was pointed out to me that that question is a duplicate of this one. Since no one has answered this question fully yet, I have decided to add this answer here as well.
As you have identified (tagged) correctly, this indeed is very similar to the matrix multiplication problem (in what order do I multiply matrixes in order to do it quickly).
This can be solved polynomially using a dynamic algorithm.
I'm going to instead solve a similar, more classic (and identical) problem, given a formula with numbers, addition and multiplications, what way of parenthesizing it gives the maximal value, for example
6+1 * 2 becomes (6+1)*2 which is more than 6+(1*2).
Let us denote our input a1 to an real numbers and o(1),...o(n-1) either * or +. Our approach will work as follows, we will observe the subproblem F(i,j) which represents the maximal formula (after parenthasizing) for a1,...aj. We will create a table of such subproblems and observe that F(1,n) is exactly the result we were looking for.
Define
F(i,j)
- If i>j return 0 //no sub-formula of negative length
- If i=j return ai // the maximal formula for one number is the number
- If i<j return the maximal value for all m between i (including) and j (not included) of:
F(i,m) (o(m)) F(m+1,j) //check all places for possible parenthasis insertion
This goes through all possible options. TProof of correctness is done by induction on the size n=j-i and is pretty trivial.
Lets go through runtime analysis:
If we do not save the values dynamically for smaller subproblems this runs pretty slow, however we can make this algorithm perform relatively fast in O(n^3)
We create a n*n table T in which the cell at index i,j contains F(i,j) filling F(i,i) and F(i,j) for j smaller than i is done in O(1) for each cell since we can calculate these values directly, then we go diagonally and fill F(i+1,i+1) (which we can do quickly since we already know all the previous values in the recursive formula), we repeat this n times for n diagonals (all the diagonals in the table really) and filling each cell takes (O(n)), since each cell has O(n) cells we fill each diagonals in O(n^2) meaning we fill all the table in O(n^3). After filling the table we obviously know F(1,n) which is the solution to your problem.
Now back to your problem
If you translate the polygon into n different formulas (one for starting at each vertex) and run the algorithm for formula values on it, you get exactly the value you want.
Here's a case where your greedy algorithm fails:
Imagine your polygon is a square with vertices A, B, C, D (top left, top right, bottom right, bottom left). This gives us edges (A,B), (A,D), (B,C), and (C, D).
Let the weights be A=-1, B=-1, C=-1, and D=1,000,000.
A (-1) ------ B (-1)
| |
| |
| |
| |
D(1000000) ---C (-1)
Clearly, the best strategy is to collapse (A,B), and then (B,C), so that you may end up with D by itself. Your algorithm, however, will start with either (A,D) or (D,C), which will not be optimal.
A greedy algorithm that combines the min sums has a similar weakness, so we need to think of something else.
I'm starting to see how we want to try to get all positive numbers together on one side and all negatives on the other.
If we think about the initial polygon entirely as a state, then we can imagine all the possible child states to be the subsequent graphs were an edge is collapsed. This creates a tree-like structure. A BFS or DFS would eventually give us an optimal solution, but at the cost of traversing the entire tree in the worst case, which is probably not as efficient as you'd like.
What you are looking for is a greedy best-first approach to search down this tree that is provably optimal. Perhaps you could create an A*-like search through it, although I'm not sure what your admissable heuristic would be.
I don't think the greedy algorithm works. Let the vertices be A = 0, B = 1, C = 2, and the edges be AB = a - 5b, BC = b + c, CA = -20. The greedy algorithm selects BC to evaluate first, value 3. Then AB, value, -15. However, there is a better sequence to use. Evaluate AB first, value -5. Then evaluate BC, value -3. I don't know of a better algorithm though.