Finding a door in an infinitly long wall - complexity-theory

Let's say you stand in front of a massive wall.
The wall is infinitly long to your right and left side. You know that there is a door somewhere and you try to find it to reach the other side.
Sadly, it is night and you can only feel the part of the wall in front of you.
You don't know how far away the door is or what direction you have to go but you can count your steps, starting from your startpoint.
How can you solve this problem?
The naive approach would be to start at the startpoint and go +1 to the right, check and if no door is found, go to the start and go -1 and check again. If there is still no door you would have to go to the start and check +2 to the right and so on....
This would result in O(n^2) steps to find the door (Where n is the number of steps from the startpoint to the door).
Is there a better way? Maybe even in O(n) steps?
I don't even exactly know what tags I should ask this so feel free to add some if you think they fit.

The problem is that you don't know which way to go, so whatever solution you come up with, you have to go back to the origin and start going the other way. Furthermore you can never rule out either of the directions until after you've found the door making you go back to origin any number of times with any algorithm with sufficiently large n (where I assume n is the distance of the door from the origin).
That means we want to go back as little as possible, but we still will have to. The solution is to not increment the step by just one, but travel twice the distance.
For simplicity without hurting the asymptotic complexity, we will travel distance d to some point, then come back, travel the same distance to the other direction and finally come back again. This only gives us constant 4 for our complexity, so we can disregard it later. Anyways when I will talk about an iteration, it means all of these 4 routes even though you will have found the door before completing all of them in the last iteration.
So in the first step you can travel to tile 2, in second to tile 4, then 8, 16, etc.
You will find the door in the k-th iteration where 2^k >= n > 2^(k-1), which means k >= log(n) > k-1. For simplicity we can assume that n is a power of 2, because for the computation it doesn't matter if n is for example 33 or 64 (or minus any of those), we will find all of these in the same iteration. So we can write k = log(n).
You are now summing just part of geometric sequence, so after k-th iteration you will have traveled total of 4 * 2*(2^k - 1)/(2 - 1) = 8 * (2^log(n) - 1) = 8 * (n - 1) = 8n - 8 = O(n).

Related

Dynamic Programming - Jumping jacks

Can some one help in solving the below problem using DP technique.
No need of code. Idea should be enough.
Marvel is coming up with a new superhero named Jumping Jack. The co-creator of this superhero is a mathematician, and he adds a mathematical touch to the character's powers.
So, one of Jumping Jack's most prominent powers is jumping distances. But, this superpower comes with certain restrictions.
Jumping Jack can only jump —
To the number that is one kilometre lesser than the current distance. For example, if he is 12 km away from the destination, he won't be able to jump directly to it since he can only jump to a location 11 km away.
To a distance that is half the current distance. For example, if Jumping Jack is 12 km away from the destination, again, he won't be able to jump directly to it since he can only jump to a location 6 km away.
To a distance that is ⅓rd the current distance. For example, if Jumping Jack is 12 km away from the destination, once more, he won't be able to jump directly to it since he can only jump to a location 4 km away.
So, you need to help the superhero develop an algorithm to reach the destination in the minimum number of steps. The destination is defined as the place where the distance becomes 1. Jumping Jack should cover the last 1 km running! Also, he can only jump to a destination that is an integer distance away from the main destination. For example, if he is at 10 km, by jumping 1/3rd the distance, he cannot reach 10/3rd the distance. He has to either jump to 5 or 9.
So, you have to find the minimum number of jumps required to reach a destination. For instance, if the destination is 10 km away, there are two ways to reach it:
10 -> 5 -> 4 -> 2 -> 1 (four jumps)
10 -> 9 -> 3 -> 1 (three jumps)
The minimum of these is three, so the superhero takes a minimum of three jumps to reach the point.
You should keep the following 2 points in mind for solving all the Dynamic programming problems:
Optimal Substructure (to find the minimum number of jumps)
Overlapping subproblems (If you encounter the same subproblem again, don't solve it, rather used the already computed result - yes, you'll have to store the computed result of sub-problems for future reference)
Always try to make a recursive solution to the problem at hand (now don't directly go ahead and look at the recursive solution, rather first try it yourself):
calCulateMinJumps(int currentDistance) {
if(currentDistance == 1) {
// return jumps - you don't need to recurse here
} else {
// find at what all places you can jump
jumps1 = calculateMinJumps(n-1) + 1
if(currentDistance % 2 == 0)
jumps2 = calculateMinJumps(n/2) + 1
if(currentDistance % 3 == 0)
jumps3 = calculateMinJumps(n/3) + 1
return minimum(jumps1, jumps2, jumps3) // takes jump2 and jump3 only if they are valid
}
}
Now you know that we have devised a recursive solution. The next step is to go and store the solution in an array so that you can use it in future and avoid re-computation. You can simply take a 1-D integer array and keep on storing it.
Keep in mind that if you go by top-down approach - it will be called memoization, and if you go by bottom-up approach - it will be called Dynamic programming. Have a look at this to see the exact difference between the two approaches.
Once you have a recursive solution in your mind, you can now think of constructing a bottom-up solution, or a top-down solution.
In Bottom-up solution strategy - you fill out the base cases first (Jumping Jack should cover the last 1 km running!) and then build upon it to reach to the final required solution.
Now, I'm not giving you the complete strategy, as it will be a task for you to carry out. And you will indeed find the solution. :) - As requested by you - Idea should be enough.
Firstly, think about this coin changing problem may help you understand yours, which are much the same:
Coin change - DP
Secondly, usually if you know that your problem has a DP solution, you can do 4 steps to solve it. Of cause you can ommit one or all of the first 3 steps.
Find a backtrack solution.(omitted here)
Find the recursion formula for your problem, based on the backtrack solution. (describe later)
Write a recursion code based on the recursion formula.(Omitted)
Write a iterating code based on step 3.(Omitted)
Finaly, for your question, the formula is not hard to figure out:
minStepFor(distance_N)=Math.min(minStepFor(distance_N-1)+1),
minStepFor(distance_N/2)+1,
minStepFor(distance_N/3)+1)
Just imagine jack is standing at the distance N point, and he has at most three options for his first go: go to N-1 point, or N/2 point, or N/3 point(if N/2 or N/3 is not integer, his choice will be reduced).
For each of his choice, the minimum steps is minStepFor(left distance)+1, since he has made 1 move, and surely he will try to make a minimum steps in his left moving. And the left distance for each choice is distance_N-1,distance_N/2 and distance_N/3.
So that's the way to understand the formula. With it it is not hard to write a recursion solution.
Consider f[1]=0 as the number of jumps required when JumpingJack is 1km away is none.
Using this base value solve F[2]...f[n] in below manner
for(int i=2; i<=n; i++) {
if(i%2==0 && i%3==0) {
f[i] = Math.min(Math.min(f[i-1]+1, f[i/2]+1), f[i/3] + 1);
}
if(i%2==0) {
f[i] = Math.min(f[i-1]+1, f[i/2]+1);
}else if(i%3==0) {
f[i] = Math.min(f[i-1]+1, f[i/3] + 1);
}else{
f[i] = f[i-1]+1;
}
}
return f[n];
You don't need to recursively solve the subproblem more than once!

Algorithm to find a point on an infinite line in time complexity O(n)

on an infinite line there is a point x with unknown position. An algorithm should find this point in time complexity O(n), where n is the distance between the start point of searching s and x. The line is divided in steps. Each step has the same length.
My idea was something like this:
start in s
go 1 step left
if x found {
terminate
}
else {
go 2 steps right
if x found {
terminate
}
else {
go 3 steps left
...
..
.
}
}
But this doesn't seam like O(n).
Any ideas?
Thanks
You have discovered the right algorithm for the job.
But this doesn't seam like O(n).
This algorithm is precisely O(n), because for each value of k between 1 and n it probes exactly twice - once on the right at the position x+k*sm, and once on the left at the position x-k*s. This means that the algorithm is O(2n), but since the constant factor is always excluded in big-O notation, your algorithm is O(n).
I guess there's some reason this "algorithm" has to "walk" from s, visiting only one place at a time, and the total time is equal to the distance walked... Otherwise you'd just move two points out from s in both directions until one of them finds the target. (I think this is what #dasblikenlight thinks you did)
If I'm reading your question correctly, then, your algorithm is on the right track, but to do this in linear time, you have to increase the distance walked in each direction exponentially when you turn around.
For instance, you could go right 1, left 2, right 4, left 8, right 16, etc. Each time you turn around, you walk over the previously covered area and then go the same distance again.
Lets say you finally find x while walking 2^m steps in some direction. The total distance you've talked is at most the sum of all 2^p for p=1...m. This works out to 2^(m+1)-1.
Furthermore you know that x is more that 2^(m-2) steps away from s, because otherwise you would have found it on an earlier pass.
2^(m+1)/2^(m-2) = 8, so the total distance walked is less than 8n, which is certainly in O(n)
think of infinite line as infinite element array and you are asked to start from an arbitrary point,
traverse some finite distance d on right and check each index if value is found, if found declare SUCCESS and exit, if not found till index d goto step 2
traverse left till distance 2d, start checking value from currentPos-d distance only, as indexes from currentPos till currentPos-d are already checked in previous iteration, if value found at any index declare SUCCESS and exit, if not found till currentPos-2d, set d=2d, goto step 3.
Traverse right till distance 2d, start checking value after currentPos+d distance only, as indexes from currentPos till currentPos+d are already checked in previous iteration, if value found at any index declare SUCCESS and exit, if not found till currentPos+2d, set d=2d, goto step 2.
This way you can avoid O(nx(n-1)) and resolve to O(n) , as you are NOT repeatedly checking values at each iteration, in step 2 and 3 where you are avoiding to check values from currentPos-d and currentPos+d , further when you set d=2d, thats where and how you are reducing algo complexity to O(n).

A person at the origin on a 1 dimensional line must step k integer values in 1 direction to find a specified k. How can this be done in O(k) steps?

A person stands at the origin of a 1 dimensional line. He is trying to get to a point that is k steps away in one direction. The direction is unknown and the distance is also unknown. How can this be done in O(k) steps.
I know the answer is probably something obvious but I can't seem to figure it out. Thanks.
The frog can hop (one pad at a time) to 1, -1, 2, -2, 4, -4, 8, -8, 16, -16 and so on. That is, the frog hops in one direction until she reaches a pad that's a never-before visited power of 2 away from the center and then starts hopping back the other way.
If the magic pad is at distance N from the center, the total number of hops will be at most 4(1+2+4+...+2^ceil(lg N)). That's 4(2^(1+ceil(lg N))-1) which is less than 16N.
The frog cannot go in one direction only or it might miss the magic lily pad; so it has to go in both directions.
The frog can only go so far in one direction before having to check the other; to cover the entire strip of lily pads it needs to go back and forth.
In one attempt, he will try to look at all lily pads at a distance less than x from his starting pad. He'll go x hops forward, 2x backwards, and x forward again, having covered 2x lily pads in 4x hops.
Making an attempt of 1, then one of 2, then one of 3 etc. will lead to too many hops, covering only n lily pads in O(n²) hops.
However, if the attempted distances are an exponential series, there's a limit on how many failed attempts he'll do before finding the magic lily pad. If he attempts 1, then 2, then 4, then 8 etc. (2^n, works for larger bases as well), he'll cover n lily pads in O(n) hops.
O(n) is defined as the maximum time-complexity, or the upper bound for completion. If you have n lily pads in a row, a straight through traversal would take at maximum O(n) because each lily pad is visited once. The only issue would be, if the frog is placed somewhere in the middle of the row (not at one end), and the rows are infinite. In that circumstance, you would need to determine which direction (left or right) to traverse the row and you have a chance of never finding the magic lily pad. Also, infinite rows implies n approaches infinity (so O(n) could be an infinitely long period of time!). I don't see an answer if the frog starts in the middle of an infinite set of rows that expand in both direction. If the frog starts at one end of an infinite set of rows, O(n) is achieved by hopping one lily pad at a time in the same direction.
The only solution I can find is to take n steps in a random direction, and if you don't end up at the magic pad, turn around and take 2n steps. So worst-case is 3n steps. 3n is proportional to n - it grows linearly. So O(n).

scheduling n people with given time of travel

this is a puzzle but i think it could be a classical algorithm which i am unaware of :
There are n people at the bottom of a mountain, and everyone wants to go up, then down the mountain. Person i takes u[i] time to climb this mountain, and d[i] time to descend it.
However, at same given time atmost 1 person can climb , and .atmost 1 person can descend the mountain. Find the least time to travel up and back down the mountain.
Update 1 :
well i tried with few examples and found that it's not reducible to sorting , or getting the fastest climbers first or vice versa . I think to get optimal solution we may have to try out all possible solutions , so seems to be NP complete.
My initial guess: (WRONG)
The solution i thought is greedy : sort n people by start time in ascending order. Then up jth person up and kth down where u[j]<= d[k] and d[k] is minimum from all k persons on top of mountain. I am not able to prove correctness of this .
Any other idea how to approach ?
A hint would suffice.
Try to think in the following manner: if the people are not sorted in ascending order of time it takes them to climb the mountain than what happens if you find a pair of adjacent people that are not in the correct order(i.e. first one climbs longer than second one) and swap them. Is it possible that the total time increases?
I think it is incorrect. Consider
u = [2,3]
d = [1,3]
Your algorithm gives ordering 0,1 whereas it should be 1,0.
I would suggest another greedy approach:
Create ordering list and add first person.
For current ordering keep track of two values:
mU - time of last person on the mountain - time of the end
mD - time of earliest time of first descending
From people who are not ordered choose the one which minimises abs(mD - d) and abs(mU - u). Then if abs(mD - d) < abs(mU - u) he should go at the beginning of ordering. Otherwise he goes at the end.
Some tweak may still be needed here, but this approach should minimise losses from cases like the one given in the example.
The following solution will only work with n <= 24.
This solution will require dynamic programming and bit-mask technique knowledge to be understood.
Observation: we can easily observe that the optimal total climb up time is fixed, which is equalled to the total climb up time of n people.
For the base case, if n = 1, the solution is obvious.
For n = 2, the solution is simple, just scan through all 4 possibilities and calculate the minimum down time.
For n = 3, we can see that this case will be equal to the case when one person climb up first, followed by two.
And the two person minimum down time can be easily pre-calculated. More important, this two person then can be treated as one person with up time is the total up time of the two, and down time is the minimum down time.
Storing all result for minimum down time for cases from n = 0 to n = 3 in array called 'dp', using bit-mask technique, we represent the state for 3 person as index 3 = 111b, so the result for case n = 3 will be:
for(int i = 0; i < 3; i++){
dp[3] = min(dp[(1<<i)] + dp[3^(1<<i)],dp[3]);
}
For n = 4... 24, the solution will be similar to case n = 3.
Note: The actual formula is not just simple as the code for case n = 3(and it requires similar approach to solve as case n = 2), but will be very similar,
Your approach looks sensible, but it may be over-simplified, could you describe it more precisely here?
From your description, I can't make out whether you are sorting or something else; these are the heuristics that I figured you are using:
Get the fastest climbers first, so the start using the Down path
asap.
Ensure there is always people at the top of the mountain, so
when the Down path becomes available, a person starts descending
immediately.The way you do that is to select first those people who
climb fast and descend slowly.
What if the fastest climber is also the fastest descender? That would leave the Down path idle until the second climber gets to the top, how does your algorithm ensures that this the best order?. I'm not sure that the problem reduces to a Sorting problem, it looks more like a knapsack or scheduling type.

finding the beginning node of a loop in a linked list?

How to find the beginning node of a loop in a given linked list ? Let's call this the cycle point
So far, I've understand the following (using slow/fast pointer):
Assume list has a non-looped part of size k
slow moves k steps
fast moves 2k steps
fast is (2k - k)= k steps ahead of slow
slow is at the beginning of loop; also known as Cycle point
fast is (LOOP_LENGTH - k) steps behind from Cycle point or slow pointer at this point
for each 1 step slow moves, fast moves 2 steps and gains on slow by 1 step.
Thus, it would take fast (LOOP_LENGTH - k) steps to meet slow and collide
This is the step I don't understand:
At this collision point, both nodes will be k steps from the front of the loop.
Once the collision point is found, move one pointer to the head of list.
Now move both pointers at the speed of 1 step / turn till the collide. The node at which they both meet is the beginning of the the loop and hence the Cycle point
Can someone please explain me step 9 and after that ?
Thanks
EDIT:
One thing I'd like to point out is, once inside the loop, fast will never overtake slow pointer. They will collide. Here's why: slow is at i and fast is assuming at i-1. when they move, slow=> i+1 and fast will be at i+1 too, hence collision. OR, slow is at i and fast is at i-2. next move, slow-> i+1; fast: i. next move, slow-> i+2, fast: i+2 and hence collision again. so fast will never be able to overtake slow, only collide once inside the loop!
Your 6. is wrong, the fast pointer is still k steps away from the slow pointer which is at the cycle point at that time; but better use ahead or behind instead of away. Plus, k may be smaller, bigger, or equal to the loop_length.
So, the fast pointer is k steps ahead of a slow one when that's reached the loop point which is, at your supposition, k steps after the start. Now, measuring on a loop, the fast pointer is k % loop_length steps ahead of the loop point. Right? If k = some_n * loop_length + r, the fast pointer is r steps ahead of the loop point, which is to say, r := k % loop_length steps ahead.
But that means that the slow pointer is loop_length - r steps ahead of the fast one, along the loop. This is a loop after all. So after loop_length - r additional steps the fast pointer will catch on to the slow one. For each step the slow pointer moves away, the fast moves closer in by two steps.
So we don't know k, we don't know loop_length or r, we only know m = k + loop_length - r = some_n * loop_length + r + loop_length - r = (some_n+1) * loop_length. The total number of steps m until the two pointers' meeting point, is a multiple of the loop length.
So now we start over, with a new pointer at the start and the slow where it met the fast, m steps ahead of the new. We move the new and the slow at equal speed, by 1 step at each time, and at the cycle point they shall meet - because when the new pointer has reached the cycle point, the second is still m steps ahead, which is to say, m % loop_length == 0 steps ahead along the loop. That way we find out what k is (we count our steps all the time), and the cycle point.
And we find loop_length by going along the loop one more time, until the two meet one more time.
see also: http://en.wikipedia.org/wiki/Cycle_detection#Algorithms
Hmm.. This kind of problem is tough to explain unless you are talking face to face. I will give it a try.
First of all in step 6: I think the fast pointer should be k distance away from the circle point.
But leave all that. We now have two cars. A fast car at twice the speed the speed of slow car.
Suppose the fast car starts in circular track at k distance away from circle point.
And the slow car starts from the circle point.
Now I am saying that both car will meet at k distance before the circle point.
Why? Because initially the fast car is at k distance from circle point. The fast car will cover n distance when completing the circle first time. Now the fast car is again at k distance from the circle point. But the slow car is at n/2 distance from circle point.
Now the fast car has to cover n-2k distance more to reach k distance before the circle point. And slow car has to cover n/2 - k = (n-2k) / 2 distance to reach k distance before the starting point. Which is exactly half the distance of the path to be covered by the fast car. And fast car is at twice the speed of the slow car.
So obviously they will meet at k distance before from circle point.

Resources