Find available "number" in a 2d array - java

I have this problem that I need to solve in the most effecient way.
I have a 2d array that contains the following:
Everything that is a 1 is a "wall" which means you cannot go through it. 2 is the entrance where you "enter" the array or map if you like. 3 are the things we need to find. Here is an example of a map:
1111111
1 3131
2 11111
1 31
1111111
This could be an example of an array that i need to look in. As you can see there is a 3 that is "unreachable, since it's surrounded by a wall "1". Which means that there are two available numbers in this array.
First we need to find the entrance. Since the entrance can be anywhere I need to search the entire array. I have done the following:
int treasureAmount = 0;
Point entrance = new Point(0,0);
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; i++){
if(map[i][j] == 2){
entrance.x =i;
entrance.y =j;
}
}
This takes O(n^2) time, and i don't really see another way to do this, since the entrance can be anywhere.
However i'm not really sure how to find the available numbers effectivly and fast. I thought about while searching the arrays for the entrance i will at the same time find the all the number 3 in the array even though some might not be accessible, and after that i'm not really sure how to effectivly find which are accessible.

You cannot do it better that O(n^2). It will take that much time just to read the array. But then you could do a depth first search to find the reachable 3's in the array. Here is the pseudo code.
main()
{
read array and mark the entrance as ent.x and ent.y and also an array threex[] and threey[] that stores all the exit position.
boolean visited[][]; //stores whether array[i][j] is reachable or not.
dfs(ent.x,ent.y);
for each element in three arrays
{
if(visited[threex[i]][threey[i]]) print ("Reachable");
else print("not reachable", threex[i], threey[i]);
}
}
int dx[]={1,0,-1,0},dy[]={0,1,0,-1}; // dx[i], dy[i] tells whether to move in E,N,W,S respectively.
dfs(int x,int y)
{
visited[x][y]=true;
for(i=0;i<4;i++)//move in all directions
{
int newx=x+dx[i],newy=y+dy[i];
//check if this is within the array boundary
if(newx>=0&&newx<N && newy>=0&&newy<N)
if(!visited[newx][newy] && array[newx][newy]!=1) // check if the node is unvisited and that it is pemissible
dfs(newx,newy);
}
}
Since each array element is taken up not more than once in the dfs function the complexity of the code is O(n^2).

When creating the array, you can keep a list of coordinates of that have the value of 2. You can traverse that list in O(n).

Since both entrance and target items can be anywhere in the array you don't have much choice, but to search everything. So, your entrance search is as efficient as it can be, and regarding the target items I recommend the maze flood fill algorithm.
However, the linked version of the algorithm favorizes one direction (like it is filling it with water, it floods "down"). To be as efficient as it can, you should make it expand in all directions (like you're filling it with gas), e.g.:
2
1 212
0 101 21012
1 212
2
The numbers represent the iterations of expansion. The expansion is made in four directions: left, right, up and down. When you reach the target item, you can find the shortest route simply by backtracking to the adjacent cell neighbour whose iteration index is lesser by one, until you return to the 0 iteration index - the entrance.

Related

Why is this the Time Complexity of this For Loop O(N)?

Is there a way to understand why the time complexity of the following is O(N), either(or both) from intuition or by proof?
What it does is basically that given the input of an integer array, we are creating the firstSmallLeft array of the same length where firstSmallLeft[i] = the first index where array[index] < array[i] when doing the back scan. (i.e., for index i, it scans from i-1, ... , j until it finds the first smaller element such that array[j] < array[i])
For Example, if input = [3,2,5,6,4,1].
firstSmallLeft would be [-1,-1,1,2,1,-1]
//input int[] array
int[] firstSmallLeft = new int[array.length];
firstSmallLeft[0] = -1;
for(int i = 1; i < array.length; i ++){
int cur = i -1;
while (cur >=0 && array[cur] >= array[i]){
cur = firstSmallLeft[cur];
}
firstSmallLeft[i] = cur;
}
An important insight is that the last entry in firstSmallLeft that received a value (at index i-1) represents the top of a stack, which is implemented as a linked list. An entry in firstSmallLeft represents an input value (as the index where it occurs is the index in the input array) and a link in the linked list (as its value is an index in firstSmallLeft). The bottom element in the stack has a null-link (-1).
In general not all elements in firstSmallLeft are in the represented stack, since some indices are skipped over. An example:
Let's say that the top of the stack is at index 100 (when i is 101), and it has as value 40, and firstSmallLeft[40] is -1, then that means we have a stack with just two elements (array[100] and array[40]), and none of the other indices in firstSmallLeft are included in the current stack. Each one of those once was on the stack, but have since been popped of the stack.
Every time cur = firstSmallLeft[cur]; is executed (in the inner loop), we actually pop an element of the stack (the linked list that starts at cur is one element shorter).
And when we do firstSmallLeft[i] = cur we push array[i] on the stack, making a reference to the part of the stack we wanted to keep.
Now this "virtual" stack is identified, we see the following:
A value is pushed exactly once on the stack, and can only be popped once from the stack, after which it is never visited again.
The overhead of evaluating the while expression once more to find that we need to exit the loop, occurs as many times as the outer loop iterates (i.e. n-1 times)
Therefore the algorithm is O(n).
You can imagine this algorithm as creating a collection of chains of elements. For each element in the array, following the chain backwards will take you to smaller and smaller values until you walk off the array.
To build the chain for the next element of the array, we start by looking at the chain of the element before us. We’ll then follow that chain for some number of steps, then form the chain for the new element by adding a link back to the place we stopped.
The key intuition here is that the length of the chains drops quickly and grows slowly. More concretely, let C be the length of the chain that starts from the current element of the array. We begin with C = 0. At each step in the algorithm, we drop C by some amount, then increment C by at most one. This means that across all n iterations of the algorithm, C increases at most n times. Therefore, since C is never negative, C can decrease at most n times. And therefore the total work spent in the inner while loop decreasing C, across all iterations of the algorithm, is O(n).
(If you’re familiar with amortized analyses and potential functions, you can also think of this as setting Φ = C.)
This same sort of argument arises in a number of other algorithms, such as building a Cartesian tree with a stack and constructing the failure table in the Knuth-Morris-Pratt string matching algorithm.

Sort int queqe with restrictions

I need to sort a queue using only one other queue, final number of variables and only with "isEmpty","enqueue","dequeue".
I'v tried to do this for a day and I just didn't figured it out yet..I searched all over the place and there is no question with that kind of restrictions, do you think that it possible?
if it's in java , this is a normal bubble sort.
public void sort(Queue<Integer> q){
//save first num into copy
Queue<Integer> copy = new Queue<Integer>();
int length=0;
while(!q.isEmpty()){
copy.add(q.remove());
length ++;
}
int maxNum, temp;
while(!copy.isEmpty()){
maxNum=copy.remove();
temp=0;
copy.add(maxNum);
//search for the max number
for(int i=0; i<length-1; i++){
temp = copy.remove();
if(temp > maxNum) maxNum= temp;
copy.add(temp);
}
//delete it from copy and add it to q
for(int i=0; i<length; i++){
temp = copy.remove();
if(temp == max){
q.add(max);
break;
}
copy.add(temp);
}
length --;
}
}
it should work.
so , explanation:
count q and save it in copy.
now you can irritate through copy knowing how many values there are in it.
so search for the max number , insert it into q and remove from it copy.
after you've done that , decrement length , because
now copy has one less element and repeat until length==0
and q is sorted.
the algorithm that sorts q and takes two more queues goes like this:
foreach element in q
while inserting q into a copy , find it's max number.
make sure you somehow inserted q into copy without the max number
and then insert it into a new sorted queue.
after you've done that , reinsert copy into q and repeat until q is empty
at the end.
the whole point in that algorithm is that we use
one extra queue to irritate through q.
and another in order to save the result while irritating.
because if we won't use another queue to irritate through q
we won't be able to know when to stop irritating.
but if we know when to stop irritating through q (knowing it's length)
we don't really need that extra queue, so we can use only one other queue.
I don't think you even need another queue. give me
half of an hour and I will program you an algorithm using
only the queue we got.
when you sort an array , using the
types of sorting algorithms that we have currently have,
in order to sort it in less than O(n^2), you have to use memory of O(n);
which is the same as saying you will NEVER use a final number of variables
if you want less than O(n^2).
you wanted it to use a final number of variables , so I automatically assumed that you just needed a simple O(n^2) algorithm.
I think you can do merge sort. I'll do it tommorow.
What is final number of variables ? Missing from the problem statement is how the front elements of each queue can be compared. Is there a size function that returns the number of elements in a queue?
For 2 queues, a bottom up merge sort can be implemented, but requires a few variables for each queue to keep track of a logical boundary in each queue. The logical boundary effectively splits each queue into two parts, a front (old) part and a back (new) part. This is a sort with time complexity of O(n log(n)).
Call the two queues A and B, with all the elements on A. If there is no size function, copy A to B to generate a count of elements.
Separate the elements evenly between A and B (one to A, one to B, ... ).
The merge sort repeatedly merges a run from A and B, alternating the merged run output between A and B. On the first pass, runs of size 1 are merged to form runs of size 2, the next pass runs of size 2 are merged to form runs of size 4, and so on, until the final pass where 2 runs are merged onto a single queue.

How to find two number whose sum is given number in sorted array in O(n)?

public static void findNumber(int number) {
int[] soretedArray = { 1, 5, 6, 8, 9 };
for (int i = 0; i <= soretedArray.length; i++) {
for (int j = i + 1; j < soretedArray.length; j++) {
if (soretedArray[i] + soretedArray[j] == number) {
System.out.println(soretedArray[i] + "::" + soretedArray[j]);
return;
}
}
}
}
Using this code I am able to find the number and its complexity is O(N^2) but I have to find this using O(N) complexity i.e using only one for loop or hash-map or similar in Java.
I remember, I was watching the official Google video about this problem. Although it is not demonstrated in java, it is explained step-by-step in different variations of the problem. You should definitely check it:
How to: Work at Google — Example Coding/Engineering Interview
As explained in the Google video that Alexander G is linking to, use two array indexes. Initialize one to the first element (0) and the other to the last element (sortedArray.length - 1). In a loop, check the sum of the two elements at the two indexes. If the sum is the number you were looking for, you’re done. If it’s too high, you need to find a smaller number at one of the indexes; move the right index one step to the left (since the array is sorted, this is the right way). If on the other hand, the sum you got was too low, move the left index to the right to obtain a higher first addend. When the two indexes meet, if you still haven’t found the sum you were looking for, there isn’t any. At this point you have been n - 1 times through the loop, so the algorithm runs in O(n).
We ought to first check the precondition, that the array is really sorted. This too can be done in O(n), so doing it doesn’t break any requirements.
The algorithm may need refinement if you are required to find all possible pairs of numbers that yield the desired sum rather than just one pair.
Is this answer superfluous when the video link has already said it? For one thing, my explanation is shorter, so if it suffices, you’re fine. Most importantly, if the video is removed or just moved to another URL, my answer will still be here.
With fixed number, for any chosen x in the array you just have to find if number-x is in the array (Note that you can also bound x). This will not give you O(n), but O(n.log(n)).
Maybe by remarking that if you have a_i and a_j (j>i), taking the sum and comparing against number, if the result is greater next interesting tests are with a_(i-1) or a_(j-1), and if result is lower next interesting tests are with a_(i+1) or a_(j+1), will give hint to linear-time?

Fast way to sort really big vector

I have a really big vector that stores 100000 different values,ranging from 0 to 50000.
They represent the cylinders on a hard disk,and I want to sort this vector according to three different algorithms used for disk scheduling.
So far,I read those 100000 values from a file,store them into a vector and then sort them according to the desired algorithm(FCFS,SCAN,SSTF).The problem is,it takes too long,because I'm doing it in the least creative way possible:
public static Vector<Integer> sortSSTF(Vector<Integer> array){
Vector<Integer> positions = new Vector<Integer>(array);
Vector<Integer> return_array = new Vector<Integer>();
int current_pos = 0,minimum,final_pos;
while(positions.size() > 0){
minimum = 999999;
final_pos = current_pos;
for(int i=0 ; i < positions.size() ; i++){
//do some math
}
}
return_array.add(final_pos);
current_pos = final_pos;
positions.removeElement(final_pos);
}
return return_array;
}
My function takes a vector as a parameter,makes a copy of it,does some math to find the desired element from the copied array and store him in the other array,that should be ordered according to the selected algorithm.But in a array with N elements,it is taking N! iterations to complete,which is way too much,since the code should do that at least 10 times.
My question is, how can I make this sorting more efficient?
Java already has built-in methods to sort a List very quickly; see Collections.sort.
Vector is old and incurs a performance penalty due to its synchronization overhead. Use a List implementation (for example, ArrayList) instead.
That said, based on the content of your question, it sounds like you're instead having difficulty implementing the Shortest Seek Time First algorithm.
See related question Shortest seek time first algorithm using Comparator.
I don't think you can implement the SSTF or SCAN algorithm if you don't also supply the current position of the head as an argument to your sorting method. Assuming the initial value of current_postion is always 0 will just give you a list sorted in ascending order, in which case your method would look like this:
public static List<Integer> sortSSTF(List<Integer> cylinders) {
List<Integer> result = new ArrayList<Integer>(cylinders);
Collections.sort(result);
return result;
}
But that won't necessarily be a correct Shortest Seek Time First ordering if it's ever possible for current_pos > 0 when you first enter the method. Your algorithm will then probably look something like this:
Collections.sort(positions);
find the indices in positions that contain the nextLowest and nextHighest positions relative to current_pos (or currentPos, if following Java naming conventions)
whichever position is closer, remove that position from positions and add it to return_array (If it was nextLowest, also decrement nextLowestIndex. If it was nextHighest, increment nextHighestIndex)
repeat step 3 until positions is empty
return return_array.
Of course, you'll also need to check for nextLowestIndex < 0 and nextHighestIndex >= positions.size() in step 3.
Note that you don't need the for loop inside of your while loop--but you would use that loop in step 2, before you enter the while loop.

For cycle [C/java like syntax]

So here I am with this simple question
Consider these two for cycles and please
explain to me if there's any difference
between the two ways of writing
method 1 :
for(i=(max-1) ; i>=0 ; i--){ do-some-stuff }
method 2 :
for(i=max ; i>0 ; i--) { do-some-stuff }
the reason I'm asking this is because today at school
while we were seeing some Java functions, there was
this palindrome method wich would use as max the
length of the word passed to it and the method used
to cycle trough the for was the first, can anyone
clarify me why the person who writed that piece of
code prefeered using that method ?
Yes, there's a big difference - in the version, the range is [0, max-1]. In the second version, it's [1, max]. If you're trying to access a 0-based array with max elements, for example, the second version will blow up and the first won't.
If the order in which the loop ran didn't matter, I'd personally use the more idiomatic ascending sequence:
for (int i = 0; i < max; i++)
... but when descending, the first form gives the same range of values as this, just in the opposite order.
Both the loops will iterate max times. But the ranges would be different:
First loop's range would be max - 1 to 0 (both inclusive)
Second second loop's range would be max to 1.
Therefore, if you are using i as an array index, or doing some work which is a function of i , dependent of i, then it will create problems for the terminal values (for example 0 is considered in the first one, where as not by the second one). But if you simply want to iterate the loop max nos of times , and do some work which is independent of the value of i, then there is no difference.

Categories

Resources