Google Interview Question for Software Engineer / Developers


Country: United States
Interview Type: Phone Interview




Comment hidden because of low score. Click to expand.
9
of 11 vote

I think this is the most suitable scenario for K-Way merge. K represents the number of sorted one dimensional arrays.

Because it is NxN array, and it is row wise and column wise sorted.
Here number of sorted arrays = number of row (or we can use columns)= N
So here K will be equal to N.

Here is algorithm:
Put the minimum element of each array (each row will be treated as a array) into a min-heap.
Then, repeatedly extract the minimum element from the heap, and replacing it by inserting the next
element from the same array.
The heap will never be bigger than N elements, so each operation (either extract-min or
insert) takes O(lg N) time.
There are O(n) operations (one insert and one extract-min
for each element), so the running time is
O(MlogN): where M = total number of elements = N^2.

Reference: CLRS (2nd Ed) problem 6.5-8

- Ajeet October 19, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
Comment hidden because of low score. Click to expand.
0
of 2 votes

Looks O(N^2 lg N).

- S O U N D W A V E October 19, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

I edited it for info. ...with more details .. pls let me know if you need complexity analysis etc.
Here is detail:
cs.stackexchange.com/questions/12853/heap-give-an-on-lg-k-time-algorithm-to-merge-k-sorted-lists-into-one-so.

- Ajeet October 19, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

It is a common problem in Cormen and in Sahani's books.

- Ajeet October 19, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Ajeet. No need for reference or comp. analysis. or book chapter bro. Work from first principles.

See above my earlier reply. I am fairly certain it is O(N^2 lgN)
Doubt it's O( NlgN )

You have to push N^2 elements in and out of an _up to_ N element min heap.
That's O(N^2) * O(lgN)

You keep editing your initial post making it look more accurate. Why not just comment reply?

- S O U N D W A V E October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
-1
of 3 votes

LOL

one man's n, is another man's N^2.

- Anonymous October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Yes it will be O(N^2 lgN) .....because N^2 will be total number of elements.

- Ajeet October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

i think it's better to use different letters. mixing 'n' and 'N' makes it unclear.
change to something like M log N, and say that M = N^2, the total amount of numbers.

- Miguel Oliveira October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Yes agree, that's why initially i posted it with O(NlogN) and that creates all confusion ...it should be .. O(MlogN): where M = total number of elements = N^2.

Edited it ...

- Ajeet October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

It seems to me that, in something like O(n), 'n' is commonly understood as referring to the number of elements one is asked to sort, etc.. NxN, in this particular question, is referring the width and height of a table which is a totally different meaning. I think people have been confusing the two.

- Michael.J.Keating October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

The definition of n in the time complexity, this is just total number of elements, so I must agree with Michael J Keating who gave us the most closed answer.
Merge Sort is just known as O(n log n), and the time complexity of his algorithm is less than Merge Soft big O analysis. The N for the 2D matrix in the question is differ from n in the time complexity computation as it is just total number of elements.. don't be confused if I am right...

- SJ Park October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

There is an N in the problem, nothing more nothing less.

some other n, some other K , redefining N=all elements .... no

- S O U N D W A V E October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

We need to stop memorizing letters along with theorems and matching them to historical studies and problems.

This is like first year physics when people got confused because the diff. equation for the spring based harmonic oscillator is x ' = something.

"Professor, but isn't it dy/dx with x independent variable? it's always f(x) = something in calculus books"

- S O U N D W A V E October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Michael and Sung:

Letters don't matter. We try to measure the size of the input with the most "independent" and "fundamental" measure possible.

Ok say we are using n or N for measuring things.
If we let n (N) be the numbers of elements, fine.
But this is equal to the square of the width of the matrix. Does it not make sense to use the width instead?

Let's see:

1) If we used number of elements, then sure we can regurgitate formulas (nlgn for mergesort, klgn or whatever for merging k lists), but does it really give insight into this specific problem?

For one, think about O(nlgn) (if we used # elem.) vs. O(n^2 lg n) (if we used width) to describe the runtime of mergesort.

Which is more useful to this problem?

2) n or N or K are irrelevant and can be interchanged for y, u, p, cats, dogs, blah in big-O.

These are "dummy variables" just like the x in f(x) or y in integral(f(y)dy).
Don't commit too many dummy variables to memory. When you study something, don't burn "n is used for this problem" , "K is used for merge lists" into your ROM.

- S O U N D W A V E October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
2
of 2 votes

Ok, this whole thread got swamped out by
1) incorrect use of bigO and letters and stating theorems
2) claiming solutions broke the theoretical minimum possible for the problem
and comparing theorems incorrectly
3) not enough discussion of the problem itself....

Time to bail, me thinks.

- S O U N D W A V E October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Yes, I understand they are dummy variables. But if the question read:

"Given a sorted 2D X * X array" instead of "Given a sorted 2D N x N array"

I imagine we would consider 'n' or 'N' the number of elements rather than the number of rows.

Also, it's not clear to me how considering O(n) to represent the row count rather than the element count is more helpful - particularly when it's clear that one must touch every element in the matrix.

- Michael.J.Keating October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

But I agree - time and energy would be better spent on the problem itself.

A couple of things my solution does not take advantage of is the properties of the table having the same width and height, and that the columns are sorted in addition to the rows. But I couldn't see how to take advantage of this.

- Michael.J.Keating October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Michael, yes the problem has an NxN.

So someone responding reasonably has two options:
1) use N without any definition, so the reason know he/she means the N defined in the problem
2) or redefine a new letter and not muddle it up with N from the problem definition

NxN means N rows and N columns.

It makes a big difference in using #rows (or columns) instead of number of elements. How about the fact the question was worded that way? Also think of "log" for one example. log wipes out the effect of squaring and pushes any effect into the bigO hidden constant, and this information is best brought to light by working with N=width.

For another, we are working with a square matrix, so do you think it's good enough to simple state theorems that were "stated" for linear arrays?

See:

For the problem itself, we have global upper and lower bounds on any optimal solution in terms of time complexity:

1) Upperbound O(N^2 lgN) <--- Because the original poster's mergesort does this

2) Lowerbound Omega(N^2) <-- Gotta touch them all. In fact, it can't be C <1 constant within the O either

- S O U N D W A V E October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

This is not faster than the naïve approach (just sort everything).

- danielkarch October 21, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

It is. If naive sorting is done (by converting 2D array to 1D array), complexity is MlogM (M = N^2). In K-way merge, complexity is MlogN (since heap only contains N elements at any time).
Side note: K-way merge sort is also used to sort extremely long arrays which cannot fit in memory - called as external merge sort.

- Roxanne November 23, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

This solution does not use all the conditions provided in the problem. For this solution to be viable, either being row-wise sorted or being column-wise sorted is enough.

- yaojingguo December 12, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Can be done in N^2. Idea is same as yours - k way merge, but uses the col sorting as well. See my soln at the bottom of the page.

- AlgChamp December 30, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Yes, this approach is not better than naive approach of mergesort.
1. Naive approach of merging and then sorting: O(N^2 * log (N^2)) = O(N^2*logN)
2. This N-way merge approach: O(N^2*log(N)).
The constants are different but the complexity is really the same.

- Zero2 July 22, 2014 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

github.com/vikhyath/c-runs/tree/master/n-way-merge

/*
Program to do to n-way merge, where n is the SIZE of n*n array
Emulating n-way merge from file through arrays, where each array row corresponds to a sorted file

Running time: O(n^2 logn), will be O(n^3) if min heap is not used

1) Get sizeof(min-heap) elements from n*n array
2) Put in min heap, remove the root element O(log n)
3) Fill min heap with a new element from array O(#elements) = O(n^2)
4) Do steps 2-3 till n*n array is exhausted
5) Now remove the root from min heap as many times as there are elements left in heap
*/

- Anonymous October 21, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 4 vote

I dont think we can do better than O(n^2). The total number of elements in the matrix is n*n and we have to visit them at least once.

- Chander October 19, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Yes, and the merging step of mergesort does it.

- Anonymous October 19, 2013 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

On an NxN matrix, wouldn't we have n=NxN? So, for a 10x10 matrix: n=100 as there are 100 elements?

- Michael.J.Keating October 19, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 2 vote

It seemed Collection Algorithm could be applicable theoretically, but using this method became more complicated in my case as there were also many internal calculation to be reordered and mapped, so firstly implemented by a general merge method with the results in Java. I only skipped minimum numbers. Can anyone try this by more efficient way of collection algorithm??
Making strategy of partial set of collection was not so difficult, but implementation by a stupid computer was not efficient even though I used iterators of Java, there could be more complicated computation than simple general merge algorithm as I failed...

public class ConvertSorted2Dto1D {
	
	final static int givenN = 5;
	
	private static void merge(int[] lArray, int lL, int lH, int[] rArray, int rL, int rH, int[] array, int min) {
		int[] arrayL = new int[lH - lL];
		int l = 0; 
		int r = rL;
		int i = min;

		System.arraycopy(lArray, lL, arrayL, 0, arrayL.length);

		// Combine left[] and right[]		
		while(l < arrayL.length && r < rH) {
			if(arrayL[l] > rArray[r]) {
				array[i++] = rArray[r++];
			} else {
				array[i++] = arrayL[l++];
			}
		}
	
		// Remaining in left[]
		while(l < arrayL.length) {
			array[i++] = arrayL[l++];
		}
	
		// Remaining in right[]
		while(r < rH) {
			array[i++] = rArray[r++];
		}
	}
	
	public static void convert2Dto1D(int[][] array2D, int[] array1D) {
		
		if(givenN > 0) {
			System.arraycopy(array2D[0], 0, array1D, 0, givenN);
			
			int min = 1;

			for(int i = 1; i < givenN; i++) {
				for(; min < i*givenN; min++) {
					if(array2D[i][0] < array1D[min]) {
						break;
					}
				}

				merge(array1D, min, i*givenN, array2D[i], 0, givenN, array1D, min);
			}
		}

	}

	public static void main(String[] args) {
		
		int[][] sorted2D = new int[givenN][givenN];
		int[] sorted1D = new int[givenN*givenN];

		for(int i = 0; i < givenN; i++) {
			for(int j = 0; j < givenN; j++) {
				sorted2D[i][j] = (int)(Math.random()*9 + i*11 + j*31); 
			}
		}
	
		System.out.println("Before");
		for(int i = 0; i < givenN; i++) {
			for(int j = 0; j < givenN; j++) {
				System.out.print(" " + sorted2D[i][j]);
			}
			System.out.println();
		}
		
		convert2Dto1D(sorted2D, sorted1D);

		System.out.println("After");
		for(int i = 0; i < givenN * givenN; i++) {
			System.out.print(" " + sorted1D[i]);
		}
		System.out.println();
	}
}

Before
2 39 65 101 125
12 42 74 110 142
26 59 88 122 154
40 72 95 133 161
46 81 107 145 173
After
2 12 26 39 40 42 46 59 65 72 74 81 88 95 101 107 110 122 125 133 142 145 154 161 173

- SJ Park October 19, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

The runtime of this approach is O(N^3). The merge sizes are
n+n
2n+n
3n+n
...
n*n+n

Summing up: (1+2+3+..+N)*(N+N) = N*(N+1)/2 * (2N) = O(N^3)

You can do it in O(N^2 log N) using the same method to merge k sorted arrays (a heap). In this question, k = n.

- Miguel Oliveira October 19, 2013 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

You should know the definition of n in time complexity, n is just total number of elements in the algorithm. The time complexity of Merge Sort is known as O(n log n), so this must be at most O(n log n)... N for the size of matrix in the question, it is differ from big O computation... so this is just like O(n log n)..

- SJ Park October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

I think Merge sort would be good way in the given condition of (array[i][j] < array[i][j+1] and array[i][j] < array[i+1][j]).
Implemented in Java with the results.

public class ConvertSorted2Dto1D {
	
	final static int givenN = 5;
	
	private static void merge(int[] lArray, int lLow, int lHi, int[] rArray, int rLo, int rHi, int[] array, int min) {
		int[] tempL = new int[lHi - lLow];
		int l = 0; 
		int r = rLo;
		int i = min;

		System.arraycopy(lArray, lLow, tempL, 0, tempL.length);

		// Combine left[] and right[]		
		while(l < tempL.length && r < rHi) {
			if(tempL[l] > rArray[r]) {
				array[i++] = rArray[r++];
			} else {
				array[i++] = tempL[l++];
			}
		}
	
		// Remaining in left[]
		while(l < tempL.length) {
			array[i++] = tempL[l++];
		}
	
		// Remaining in right[]
		while(r < rHi) {
			array[i++] = rArray[r++];
		}
	}
	
	public static void convert2Dto1D(int[][] array2D, int[] array1D) {
		for(int i = 1; i < givenN; i++) {
			if(i == 1)
				merge(array2D[0], 0, givenN, array2D[1], 0, givenN, array1D, 0);
			else
				merge(array1D, i, i*givenN, array2D[i], 0, givenN, array1D, i);
		}
	}

	public static void main(String[] args) {
		
		int[][] sorted2D = new int[givenN][givenN];
		int[] sorted1D = new int[givenN*givenN];

		for(int i = 0; i < givenN; i++) {
			for(int j = 0; j < givenN; j++) {
				sorted2D[i][j] = (int)(Math.random()*9 + i*11 + j*31); 
			}
		}
	
		System.out.println("Before");
		for(int i = 0; i < givenN; i++) {
			for(int j = 0; j < givenN; j++) {
				System.out.print(" " + sorted2D[i][j]);
			}
			System.out.println();
		}
		
		convert2Dto1D(sorted2D, sorted1D);

		System.out.println("After");
		for(int i = 0; i < givenN * givenN; i++) {
			System.out.print(" " + sorted1D[i]);
		}
		System.out.println();
	}
}

Before
5 35 67 100 125
14 49 79 106 139
23 55 89 117 147
40 70 96 130 160
52 79 106 137 175
After
5 14 23 35 40 49 52 55 67 70 79 79 89 96 100 106 106 117 125 130 137 139 147 160 175

- SJ Park October 19, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

one way i could think of is having N iterators for N rows,
Take the min val from N iterators, add to your 1D array..
then Move the Iterator having Min val to Next..
if iterator.hasNext is None.. then remove that iterator from comparing List of N iterators

- Sidhartha October 19, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

This is what my solution is doing. See above..

- Michael.J.Keating October 19, 2013 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

Or, at least it's very close :). I'm using an iterator with a array of indexes - one to each row. Same algorithm, really.

- Michael.J.Keating October 19, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 2 vote

In this code, I just use the merge part of merge sort to achieve a O(n) time.

public void reduceDimensionality(int[][] array){
		
		int [] odarray = new int[array.length * array[0].length];
		int[] pointers = new int[array.length];
		int count = 0;
		while(count < (array.length * array[0].length)){
			int min = 9999999;
			int pointer = 0;
			for(int k = 0; k < pointers.length; k++){
				if( pointers[k] < array[0].length && array[k][pointers[k]] < min){
					min = array[k][pointers[k]];
					pointer = k;
				}
			}
			odarray[count] = array[pointer][pointers[pointer]];
			count++;
			pointers[pointer]++;
			
		}
		
		for(int i = 0; i < odarray.length; i++){
			System.out.print(odarray[i] + " ");
		}
		
		
	}

- Aravind October 20, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

can you explain your algorithm?

- alex October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

is this O(n^3) ....

- Yi October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

In merge sort we have 2 arrays to merge. Here I use the same algorithm to merge n algorithms.

- Aravind October 21, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

n arrays*

- Aravind October 21, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@aravind: This won't be O(n)

- alex October 21, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

This looks like same algorithm I used.
If N=rows it's O(N^3).
If n=elements it's O(n sqrt(n))

- Michael.J.Keating October 21, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 2 vote

use dynamic programming.
Split N*N array to 4 2D array
A1 A2
B1 B2

all the elements in A1 is smaller than the elements in B2
So we have concatenate A1 and B2 to C
then we need to merge A2 and B1 to C
the time complexity is N^2 * log4 N

- mengmeng October 20, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

could you tell me where is wrong? I think this is doable.

- doubao October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

The faster solution is merge sort by all rows (or columns) at the same time.
To do this, we need min-heap.
Here is how to *use* MinHeap for sorting. MinHeap does not implemented is this code. You can find the implamantation in google if you need.

template<class T> class MegreSort2d 
{
struct Link 
{
	Link(const T** data, int i, int j) 
		: i(i), j(j), value(data[i][j]) {}
	const int i, j;
	const T& value;
};
static void sort(const T** data, T* outData, int n) 
{
	MinHeap<Link> heap;
	current_mins.add(Link(data, 0,0));
		
	for(size_t i=0; i<n*n; ++i)
	{
		const Link& link  = heap.getMinValue();
		outData[i]=link.value; //save as sorted
			
		if(link.i<(n-1))
			heap.add(Link(data, link.i+1,link.j)); //add next value from this row
			
		if(link.i==0 && link.j<(n-1))
			heap.add(Link(data, 0,link.j+1)); //add first value from next row

		heap.remove(link);
	}
}
};

- Darida October 20, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

This was my first idea, re-posted from the other thread:

Treat the matrix has a (quasi) min heap:

LEFT(i, j ) = A[i+1,j]   //left child
RIGHT(i, j ) = A[i, j+1]  //right child

Note, the matrix is a kind of quasi-min-heap to begin with:
1) A[0,0] - top left - is the minimum of all elements
2) Every node A[i,j] is < LEFT, RIGHT children (as defined above) 

So we can create an aux. min. heap, 
store (0,0) in there, then:

while( aux.min.heap not empty)
{
    x=extractMinAux;
    storeInResultArray(x);
    insertMinAux( children of x 
                        THAT are not descendents    //descendent check is easy O(1)
                         of elements already in aux.min heap );
}

return result array

- S O U N D W A V E October 20, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

1  2  3  4 
 5  6  7  8
 9 10 11 12
13 14 15 16

^^^ One one type of extreme case it should run in N^2 :)
Because the axillary mean heap will never have more than 2 elements.

One the other type of extreme case (you know what it is right?), the auxillary min heap will grow from size 1 to N then back down to 1 (roughly)

So it will be roughly ~ C*N * lg(H(N)) where H(N) is the hyperfactorial function
This should be theta bound N^2 *lg(N)

{But not as TIGHT a bound to N^2(lg(N)) as the merge K sorted list thing idea people are using, because in that idea the min heap is almost always having N elements}

So if someone with time can
1) Try to make this idea work (fill in details)
2) Calculate the "expected" runtime based on a reasonable probability distribution on the valid matrix inputs of size NxN.

Maybe expected is closer to ~C*N^2 (best case) than ~C*N*lg(H(N)) (worst)
and it pops out to be some nonsense like N^2 lg(lg(N)) ?

There is hope because:
1) the "worst" case type of input matrix is not going to happen all the time
{Is seems less likely than the best case type of input above}
2) even in the worst case, the min heap grows to size N and back down (doesn't stay at size N for most of the running of algorithm like the merging N lists alg.).

{ Above is my first idea from other thread. Haven't refined it because the other thread got bogged down. }

- S O U N D W A V E October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

I haven't checked the details above no paper yet either.

- S O U N D W A V E October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

priority_queue<int,vector<int>,greater<int>>heap;
	int id=(MAXLength*MAXLength)-1;
	int index=0;
	int *result=new int[id];
	memset(result,-1,sizeof(int)*id);
	
	for(i=MAXLength-1;i>=0;i--)
	{
		for(j=MAXLength-1;j>=0;j--)
			heap.push(a[i][j]);
	}
	while(!heap.empty())
	{
		result[index++]=heap.top();
//		cout<<heap.top()<<"  ";
		heap.pop();
	}
	for(i=0;i<index;i++)
		cout<<result[i]<<"  ";
	cout<<endl;

- Anonymous October 21, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

The best algorithm here will use a Min heap as follows.

1. Create a min heap. add array[0][0] to this heap.

2. Now, iteratively do the following:
    2.1-> pop the min element in the heap.
    2.2-> if element popped was a[i][j], then do the following:
          2.2.1 --> if a[i+1][j-1] has already been popped, or if j = 0, you can insert element a[i+1][j] into the heap. do not do this if j = n-1(last column)
          2.2.2 --> if a[i-1][j+1] has already been popped, or if i = 0, you can insert element a[i][j+1] into the heap. do not do this if i = n-1(last row).

3. Rinse and repeat step 2 until there are no more elements left to pop.

This algorithm also has a worst case complexity of O(N^2logN), but works much better in the average case.

- Anonymous October 21, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

void Sorted_Matrix_2_Array(int a[MAXLength][MAXLength], vector<int> &result)
{
	int i;
	priority_queue<int,vector<pair<int,pair<int,int>>>,greater<pair<int,pair<int,int>>>>heap;
	
	for(i=0;i<MAXLength;i++)
		heap.push(make_pair(a[i][0],make_pair(i,0)));

	while(!heap.empty())
	{
		pair<int,pair<int,int>>p=heap.top();
		heap.pop();
		result.push_back(p.first);
		pair<int,int>q=p.second;
		q.second++;
		if(q.second < MAXLength)
			heap.push(make_pair(a[q.first][q.second],make_pair(q.first,q.second)));
	}	
}

- Anonymous October 22, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

You could flatten the 2D array down to a 1D array then bubble sort it since it is mostly sorted. With a a mostly sorted list you have a best case O(n) operation.

If you want you can also use Insertion Sort since the 2D array means the array is mostly sorted. That would also give you a best case of O(n)

- Anonymous October 27, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

You can view the lower diagonal part of the matrix as a max heap and the upper diagonal part as min heap. The parent-left-right relationship established by the adjacent cells, i.e. (i,j) is a parent, (i+1, j) is the left child and (i, j+1) the right child. So you just need to do a heapsort with the relation established and it seems you can't really beat O(n^2 log(n)) as otherwise heapsort would sort faster than O(n log(n)) an array of n elements. You'd then have to merge the results of 2 heaps.

- Igor October 29, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

mergesort is NMlog(NM)
my answer is
log(N)*NM on worst case

{{import java.util.Arrays;
import java.util.Set;
import java.util.TreeSet;

class Converter{
int[][] array;

class Point implements Comparable{
int r,c;
Point(int r, int c){
this.r = r;
this.c = c;
}
int get(){
return array[r][c];
}
int compaireTo(Point b){
return new Integer(get()).compareTo(b.get());
}
@Override
public int compareTo(Object b) {
// TODO Auto-generated method stub
Point pb = (Point) b;
return new Integer(get()).compareTo(pb.get());
}
}

int[] convert2Dto1D(int[][] array){
this.array = array;
TreeSet<Point> candidates = new TreeSet<Point>();
int L = array.length * array[0].length;
int[] answer = new int[L];
candidates.add(new Point(1, 0));
candidates.add(new Point(0, 1));
answer[0] = array[0][0];
for(int i = 1; i < L; i++){
Point p = candidates.pollFirst();
if(p == null){
continue;
}
answer[i] = p.get();
if(p.r + 1 < array.length){
candidates.add(new Point(p.r + 1, p.c));
}
if(p.c + 1 < array[0].length){
candidates.add(new Point(p.r, p.c + 1));
}
}
return answer;
}

public static void main(String[] argv){
int[][] array = {{0, 1, 5}, {2, 4, 6}, {3, 7, 8}};
Converter c = new Converter();
System.out.println(Arrays.toString(c.convert2Dto1D(array)));
}

}
}}

- kuroobi October 29, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Time complexity for the following algorithm is N^2*lg(PriorityQueue.size). It is similar to the general k-way merge. But it only puts an item into the priority queue if there are no items adjacent to it from left or up. Since PriorityQueue.size is less than or equal to N, this algorithm is faster than the general k-way merge.

import heapq

def convert_2D_to_1D(aa, n):
  a = [None] * (n * n)
  idx = 0
  pq = []
  visits = {}
  heapq.heappush(pq, (aa[0][0], (0, 0)))
  while len(pq) > 0:
    # print("priority queue size: ", len(pq))
    top = heapq.heappop(pq)[1]
    x = top[0]
    y = top[1]
    a[idx] = aa[x][y]
    idx += 1
    if x < n - 1:
      item = (x + 1, y)
      if y == 0:
        heapq.heappush(pq, (aa[x + 1][y], item))
      elif item in visits:
        heapq.heappush(pq, (aa[x + 1][y], item))
        del visits[item]
      else:
        visits[item] = True
    if y < n - 1:
      item = (x, y + 1)
      if x == 0:
        heapq.heappush(pq, (aa[x][y + 1], item))
      elif item in visits:
        heapq.heappush(pq, (aa[x][y + 1], item))
        del visits[item]
      else:
        visits[item] = True
  return a

# 4 * 4 2D array
n = 4
aa = [
    [1, 2,  4,  6],
    [2, 4,  5,  8],
    [4, 6,  12, 13],
    [8, 10, 18, 19]
]
print(aa)
print(convert_2D_to_1D(aa, n))

# 10 * 10 2D array
n = 10
aa = [[j for j in xrange(n)] for i in xrange(n)]
for i in xrange(n):
  for j in xrange(n):
    aa[i][j] += i
print(aa)
print(convert_2D_to_1D(aa, n))

- yaojingguo December 12, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

You dont actually need a heap - can do in O(N^2). Idea is very similar to k-way merge on rows, but uses additional property that cols are sorted as well.

First merge row 0, col 0
Then move to [1][1], merge row 1, col1
Then move to [2][2], merge row 2, col2
O(N^2).
Pseudo code:

int onedarr[] = new int[N*N];
int ctr = 0;
for(int step = 0; step < N; ++step)
{
	int rowIndex = step;
	int colIndex = step;
	onedarr[++ctr]  = arr[rowIndex][colIndex];
	for(int i = step+1; i < N; ++i)
	{
		if(rowIndex == N-1 || arr[i][colIndex] < arr[rowIndex][i])
		{
			onedarr[++ctr] = arr[i][colIndex++];
		}
		else
		{
			onedarr[++ctr] = arr[rowIndex++][i];
		}
	}
}

- AlgChamp December 30, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Hi guys,

Here's my take on the exercise in Scala. It seems to me it has O(M * N * lg N) complexity. Although I'm having a hard time justifying it in the lg N part. Maybe you can give me a hand!

At any given point in the algorithm, the number of elements in the priority queue is <= N. The number of comparisons we do between elements is at most lg N. Will there ever be repeated comparisons to make the lg N actually be lg N^2?

object KWayMerge {
  case class Entry[T <% Ordered[T]](value: T, array: Int) extends Ordered[Entry[T]] {
    override def compare(that: Entry[T]) = {
      -value.compare(that.value)
    }
  }

  def treat[T <% Ordered[T]](entry: Entry[T], indexes: Array[Int], chunks: Array[Array[T]], result: Queue[T], pq: PriorityQueue[Entry[T]]) = {
    val value = entry.value
    val arrayN = entry.array
    val array = chunks(arrayN)

    indexes(arrayN) = indexes(arrayN) + 1

    if (indexes(arrayN) < array.length) {
      pq += Entry(chunks(arrayN)(indexes(arrayN)), arrayN)
    }

    result.enqueue(value)
  }

  def kWayMerge[T <% Ordered[T]](chunks: Array[Array[T]]): Iterable[T] = {
    val result = new Queue[T]()

    val indexes = new Array[Int](chunks.length)

    for (i <- 0 until indexes.length) {
      indexes(i) = 0
    }

    val pq = new PriorityQueue[Entry[T]]()

    for (i <- 0 until chunks.length) {
      val currIndex = indexes(i)
      val arr = chunks(i)
      val current = arr(currIndex)

      pq += Entry[T](current, i)
    }

    while (!pq.isEmpty) {
      val min = pq.dequeue()
      treat(min, indexes, chunks, result, pq)
    }

    result

}}

- Sérgio Silva January 26, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Dijkstra's algorithm (search Dijkstra's Algorithm WIKI) with min priority queue gives us nlogn solution

- Dmitry January 25, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 5 vote

On a 3x3 array (n=9), this solution does 27 comparisons if I'm not missing something.
Anyway, I believe this should be O(n x sqrt(n)) complexity.

public static int[] convert2DArrayto1DArray(int[][] array) {
		
		if (array == null)
			return null;
		
		// example inputs:
		// [1,4,7]  [1,2,3]
		// [2,5,8]  [4,5,6]
		// [3,6,9]  [7,8,9]
		
		// desired output:
		// [1,2,3,4,5,6,7,8,9]
		
		// allocate the target array
		int[] target = new int[array.length * array.length]; // NxN
		
		// merge the sorted arrays		
		int[] currentIndexes = new int[array.length];
		for (int i = 0; i < target.length ; i++) {
			
			// which array has our next value?
			int arrayWithValue = 0;
			int minValue = Integer.MAX_VALUE;
			for (int j = 0; j < currentIndexes.length; j++) {
				
				// have we reached the end of this array already?
				if (currentIndexes[j] > array.length - 1)
					continue;
				
				// possible next value from this array?
				if (array[j][currentIndexes[j]] < minValue) {
					minValue = array[j][currentIndexes[j]];
					arrayWithValue = j;
				}
			}
			
			target[i] = minValue;
			currentIndexes[arrayWithValue]++;
		}
		
		return target;
	}

   public static void test() {
	   
	   int[][] arrays = {
		   {1,4,7},
		   {2,5,8},
		   {3,6,9}};
	   
	   int[] array = Util.convert2DArrayto1DArray(arrays);
	   for (int value : array)
		   System.out.print(value + " ");
   }   

// output:
// 1 2 3 4 5 6 7 8 9

- Michael.J.Keating October 19, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 2 votes

Cool, it seems you found the closed solution!!!
I was going to try like this, but it gave me pain to find the answer in a short time, so I tried the general merge method first...

- SJ Park October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
-2
of 2 votes

n^(3/2) best so far

- lite.on.beta October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

for (int i = 0; i < target.length ; i++)

Here target contains N*N elements and ignoring the inner for loop, this iteration itself is O(N^2).

Isn't this a O(N^3) solution?
I tried doing same yesterday, keeping i (index in target 1-D array) fixed and finding the candidates for index i. There are over N candidates for a position.

For position (0) there are 0 candidates, (0,0) is the smallest.
For position (1) there are N candidates, N-1 candidates in column1 and 1 candidate at (o,1).
For position (2) there are 2N-2 candidates, elements in column0 and column1 excluding those that have been picked for 0th and 1st index.

I tried various approaches but I couldn't do better than O(N^2logN) and I think that's the best we can do. Atleast I am not able to think of any method that gives next element in target 1-D array in O(1) time and every element needs to be scanned atleast once O(N^2).

Please let me know, if I am missing something.

- varun October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@varun: He has taken n to be equal to n2. eg: n=9 if dim of array = 3.

- alex October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

LOL.

Nice way to trick people into thinking this is best solution...

- Anonymous October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 2 votes

I'm not trying to trick anyone, really :)

If you have a table, for instance, of 10 rows and and 10 columns (NxN) and you are asked to sort the entire table into a single array, you have 100 elements to deal with - not 10. n=100 for big O analysis. If your table was 5 rows and 20 columns, you would also have an n=100 situation - not n=5, not n=20. The N in NxN is not the number of elements - it's the height and width of the matrix.. n, on the other hand, is the number of elements your algorithm is dealing with. That's how I see it :)

- Michael.J.Keating October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

If we are taking N to mean the number of total elements, let's call the dimensions X so N = X*X.
This can be beaten by using a heap to store the current set of minimum elements per array (rather than searching for the minimum each step which costs X steps). Removing minimum from heap costs log X, inserting next value costs log X.
So total complexity is O(N log(sqrt(N))

- shinsetsu October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

shinsetsu,

You cannot do this in an effort to justify use of N=num elements: => "So total complexity is O(N log(sqrt(N)))"

Because, log(sqrt(N)) = log(N) inside big O/theta
log wipes out any polynomial.

Even for a 1D array mergesort we can say merge sort's runtime is T(N) = O(N log(any_polynomial(N))) and we would be correct, but we lose precision.

We have to work with the "X" from your post directly.

- S O U N D W A V E October 21, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

wipes out any polynomial or power function (even fractional) *

- S O U N D W A V E October 21, 2013 | Flag
Comment hidden because of low score. Click to expand.
-1
of 1 vote

one way i could think of is having N iterators for N rows,
Take the min val from N iterators, add to your 1D array..
then Move the Iterator having Min val to Next..
if iterator.hasNext is None.. then remove that iterator from comparing List of N iterators

- Sidhartha October 19, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

I got the solution in O(n). Do verify and reply

import java.io.*;
import java.util.Scanner;

class arraysort2d
{
 public int n;
 public int irows, jrows,icols,jcols;
  
public static void main(String args[])
{
  arraysort2d obj = new arraysort2d();
  obj.input_array(); 
}

public int get_input()
{
  Scanner input = new Scanner(System.in);
  String answer = input.nextLine();
  return(Integer.parseInt(answer));
}

public void input_array()
{
  int i,j,count = 0, rval = 0;
  System.out.println("Input the value of N   ");
  n = get_input();
  System.out.println(" Value of N   " + n);
  int arr[][] = new int [n][n];
  int array1d[] = new int[n*n];
  
  System.out.println("Input the array  ");
   for (i = 0; i < n; i ++)
   {
     for (j = 0; j < n; j ++)
	 {
	   arr[i][j] = get_input();
	 }
   }
   
    System.out.println(" The array is   ");
	for (i = 0; i < n; i ++)
   {
     for (j = 0; j < n; j ++)
	 {
	   System.out.print(" " + arr[i][j]) ;
	 }
	   System.out.print("\n");
   }
  // ------------ Computation starts----------------------- 
   irows = 0;
   jrows = 1;
   icols = 1;
   jcols = 0;
   array1d[rval++] = arr[0][0];
   
   while(++count < n * n)
   {
     if (arr[irows][jrows] < arr[icols][jcols])
	 {
	   array1d[rval++] = arr[irows][jrows];
	   if(jrows == n-1)
	   {
	    if(icols == n-1)
	      jrows = n-1;
		else
		  jrows = 1;
		
		irows += 1;
	   }
	   else
	    jrows ++;
	 }
	 else
	 {
	   array1d[rval++] = arr[icols][jcols];
	   if(icols == n-1)
	   {
	     if(jrows == n-1)
	       icols = n-1;
	     else
		   icols = 1;
	
		 jcols +=1;
	   }
	   else
	     icols ++;	   
	 }
   }
   System.out.print(" " + count + " " + rval + "\n");
   array1d[--rval] = arr[n-1][n-1];
   
 //---------- Computation ends -------------
   
   for ( i = 0; i < n*n; i ++)
    {
	  System.out.print(" " + array1d[i]);
	}
   
}
 
}

- omega1991 October 20, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Your main loop reads "while(++count < n * n)" how is this O(n)?!

- Anonymous October 21, 2013 | Flag
Comment hidden because of low score. Click to expand.
-1
of 1 vote

I got the solution in O(n). Do verify and reply

import java.io.*;
import java.util.Scanner;

class arraysort2d
{
 public int n;
 public int irows, jrows,icols,jcols;
  
public static void main(String args[])
{
  arraysort2d obj = new arraysort2d();
  obj.input_array(); 
}

public int get_input()
{
  Scanner input = new Scanner(System.in);
  String answer = input.nextLine();
  return(Integer.parseInt(answer));
}

public void input_array()
{
  int i,j,count = 0, rval = 0;
  System.out.println("Input the value of N   ");
  n = get_input();
  System.out.println(" Value of N   " + n);
  int arr[][] = new int [n][n];
  int array1d[] = new int[n*n];
  
  System.out.println("Input the array  ");
   for (i = 0; i < n; i ++)
   {
     for (j = 0; j < n; j ++)
	 {
	   arr[i][j] = get_input();
	 }
   }
   
    System.out.println(" The array is   ");
	for (i = 0; i < n; i ++)
   {
     for (j = 0; j < n; j ++)
	 {
	   System.out.print(" " + arr[i][j]) ;
	 }
	   System.out.print("\n");
   }
  // ------------ Computation starts----------------------- 
   irows = 0;
   jrows = 1;
   icols = 1;
   jcols = 0;
   array1d[rval++] = arr[0][0];
   
   while(++count < n * n)
   {
     if (arr[irows][jrows] < arr[icols][jcols])
	 {
	   array1d[rval++] = arr[irows][jrows];
	   if(jrows == n-1)
	   {
	    if(icols == n-1)
	      jrows = n-1;
		else
		  jrows = 1;
		
		irows += 1;
	   }
	   else
	    jrows ++;
	 }
	 else
	 {
	   array1d[rval++] = arr[icols][jcols];
	   if(icols == n-1)
	   {
	     if(jrows == n-1)
	       icols = n-1;
	     else
		   icols = 1;
	
		 jcols +=1;
	   }
	   else
	     icols ++;	   
	 }
   }
   System.out.print(" " + count + " " + rval + "\n");
   array1d[--rval] = arr[n-1][n-1];
   
 //---------- Computation ends -------------
   
   for ( i = 0; i < n*n; i ++)
    {
	  System.out.print(" " + array1d[i]);
	}
   
}
 
}

- omega1991 October 20, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

So it seems no better solution than simply converting to 2D and then sorting it? Since all are N^2*lg(N) ?

- Yi October 20, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Since the original input is already sorted we may use this and avoid re-sorting thus providing N^2 complexity

- sobercheg October 21, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

if you simply converting it to 1D and then sorting it - it will be N^2*lg(N^2).

- Darida October 21, 2013 | Flag
Comment hidden because of low score. Click to expand.
-1
of 1 vote

So it seems no better solution than simply converting to 2D and then sorting it? Since all are N^2*lg(N) ?

- Yi October 20, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

What about the following recursive algorithm? It looks a bit complex and it's readability could be improved though :)

public class Array2Dto1D {

    public static int[] convert(int[][] array2D) {
        int[] columnIndex = new int[array2D.length];
        int[] output = new int[array2D.length * array2D[0].length];
        convertInternal(array2D, columnIndex, 0, output, 0, Integer.MAX_VALUE);
        return output;
    }

    private static int convertInternal(int[][] array2D, int[] rowIndex, int column, int[] array1D, int array1Dindex, int limit) {
        if (column >= array2D.length) return array1Dindex;

        int array1DNextIndex = array1Dindex;
        for (int row = rowIndex[column]; row < array2D[column].length; row++) {
            int value = array2D[column][row];
            // try the next column if it exists and if it's next value is less than the next value of the current column
            boolean tryNextColumn = column < array2D.length - 1 && value > array2D[column + 1][rowIndex[column + 1]];
            if (tryNextColumn) {
                array1DNextIndex = convertInternal(array2D, rowIndex, column + 1, array1D, array1DNextIndex, value);
            }
            // cannot process remaining elements in the column until elements in previous columns are not processed
            if (value > limit) return array1DNextIndex;
            rowIndex[column] = row + 1;
            array1D[array1DNextIndex++] = value;
        }
        return convertInternal(array2D, rowIndex, column + 1, array1D, array1DNextIndex, Integer.MAX_VALUE);
    }

    public static void main(String[] args) {
        int[][] A = new int[][]{
                {1, 2, 3, 300, 301},
                {100, 101, 102, 400, 401},
                {200, 500, 501, 502, 503},
        };
        int[] output = convert(A);
        int[] expected = {1, 2, 3, 100, 101, 102, 200, 300, 301, 400, 401, 500, 501, 502, 503};
        compare(output, expected);

        A = new int[][]{{1}};
        output = convert(A);
        expected = new int[]{1};
        compare(output, expected);

    }

    private static void compare(int[] output, int[] expected) {
        System.out.println(Arrays.toString(output));
        System.out.println("As expected: " + Arrays.equals(expected, output));
    }

}

- sobercheg October 21, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;


public class MatrixToOneDim {
class Indices {
int i;
int j;
public Indices(int i, int j) {
// TODO Auto-generated constructor stub
this.i = i;
this.j = j;
}
@Override
public boolean equals(Object arg0) {
// TODO Auto-generated method stub
if(! (arg0 instanceof Indices)) {
return false;
}
Indices point = (Indices)arg0;
return this.i == point.i && this.j == point.j;
}
@Override
public int hashCode() {
// TODO Auto-generated method stub
return Integer.parseInt("" + this.i + this.j + "");
}
}
int output[];
int count;
int arr[][];
int n;
public MatrixToOneDim (int arr[][], int n) {
this.arr = arr;
this.n = n;
this.count = 0;
this.output = new int[n*n];
}

public void convert() {
output[count++] = arr[0][0];
Map<Indices, Boolean> threePoints = new HashMap<Indices, Boolean>();
threePoints.put(new Indices(1, 0), true);
threePoints.put(new Indices(0, 1), true);
this.convertRecur(threePoints);
}

public void convertRecur(Map<Indices, Boolean> threePoints) {
if(threePoints.size() == 0) {
return;
}
Indices ind = findMin(threePoints);
threePoints.remove(ind);
output[count++] = arr[ind.i][ind.j];
boolean firstPresent = threePoints.containsKey(new Indices(ind.i+1, ind.j));
boolean secondPresent = threePoints.containsKey(new Indices(ind.i, ind.j+1));

if(ind.i+1 < n && ind.j+1 < n) {
if(! firstPresent && ! secondPresent && threePoints.size() < n - 1) {
threePoints.put(new Indices(ind.i+1, ind.j), true);
threePoints.put(new Indices(ind.i, ind.j+1), true);
} else if(! firstPresent && ! secondPresent) {
threePoints.put(arr[ind.i+1][ind.j] < arr[ind.i][ind.j+1] ? new Indices(ind.i+1, ind.j) : new Indices(ind.i, ind.j+1), true);
} else {
if(firstPresent)
threePoints.put(new Indices(ind.i, ind.j+1), true);
else {
threePoints.put(new Indices(ind.i+1, ind.j), true);
}
}
} else if(ind.i+1 < n && !firstPresent) {
threePoints.put(new Indices(ind.i+1, ind.j), true);
} else if(ind.j+1 < n && !secondPresent) {
threePoints.put(new Indices(ind.i, ind.j+1), true);
}

convertRecur(threePoints);
}

private Indices findMin(Map<Indices, Boolean> threePoints) {
int min = Integer.MAX_VALUE;
Indices indMin = null;
for(Entry<Indices, Boolean> entry : threePoints.entrySet()) {
Indices ind = entry.getKey();
if(min > arr[ind.i][ind.j]) {
min = arr[ind.i][ind.j];
indMin = ind;
}
}
return indMin;
}
public static void main(String[] args) {
int arr[][] = {{2, 39, 65, 101, 125},
{12, 42, 74, 110, 142},
{26, 59, 88, 122, 154},
{40, 72, 95, 133, 161},
{46, 81, 107, 145, 173}}; //{{1, 3, 6, 10, 15}, {2, 5, 9, 14, 19}, {4, 8, 13, 18, 22}, {7, 12, 17, 21, 24}, {11, 16, 20, 23, 25}};
MatrixToOneDim mat = new MatrixToOneDim(arr, 5);
mat.convert();
for (int i = 0; i < mat.output.length; i++) {
System.err.print(mat.output[i] + " ");
}

}
}

- Anonymous October 21, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

I was just thinking of an approach which is O(n)
just consider an array like

a[][]= 
 1 2 3
 4 5 6
 7 8 9

now we start with 1 i.e. a[0][0] our result array contains {1}, now we compare it with a[0][1] and a[1][0] i.e. we compare it with 2 and 4 and we select minimum of them i.e. a[0][1] which is 2, so now our result array is {1,2} now we take index a[0][1] and compare it with a[1][1] and a[0][2] where we find a[0][2] is minimum and hence select it, so now result array is {1,2,3} now we go to a[0][2] and because we are at last column we compare it with a[1][2] and a[1][0] which would get us 4, so now result array would be {1,2,3,4} and so on. one condition we need to make sure is of visited which would come in last column, in which we would compare elements with current element and check if compared ones are less than current element or not..if it is ignore that element

coding it won't be that difficult and complexity is O(n) as each element is accessed only once. (i will try coding in sometime)

- Nirav Nagda December 12, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Can you please let me know why it is down voted?.. I would like to know the reason why this solution won't work

- Nirav Nagda December 12, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

The number of the candidates for the next smallest item is not constant. For details, you can check my solution.

- yaojingguo December 12, 2013 | Flag
Comment hidden because of low score. Click to expand.
-2
of 2 vote

The updates on the right show this activity:

ender said Hi Urik, yes, I have rephrased some sentences to make ...
ender up-voted EOF's comment: Since the matrix has ...
ender up-voted URIK LAGNES's comment: 1) O(N ...

- S O U N D W A V E October 19, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

ender, your original post with strong opinions and N^2 code has disappeared, now the replies are just floating...

- S O U N D W A V E October 19, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Another comment for you to downvote :)
ender, you can downvote each comment separately

- S O U N D W A V E October 19, 2013 | Flag
Comment hidden because of low score. Click to expand.
-2
of 2 vote

We can use tree map for the same, since tree map use BST for sorting the elements and on the top of that red black tree balancing act.
Hence it will be done maximum in O(logN), please find the code below.

import java.util.*;


public class SortTwoDArray {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Integer[][] twoDArray={{1,13,45,23,56},{12,14,16,122,343},{18,100,105,178,156},{3,5,6,7,8},{0,99,205,232,1211}}; 
		sortTwoDArray(twoDArray);

	}

	private static void sortTwoDArray(Integer[][] twoDArray) {
		Set<Integer> sortedSet=new TreeSet<Integer>();
		for(Integer[] outerArray : twoDArray){
			
			for(Integer element : outerArray)
			{
				sortedSet.add(element);
			}
		}
		
		
		System.out.print("SortedArray : ");
		
		for(Integer element : sortedSet)
		{
			System.out.print(element+" ");
		}
	
		
	}

}

- Ankit garg October 19, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Let me correct myself,i used TreeSet not TreeMap

- Anonymous October 19, 2013 | Flag
Comment hidden because of low score. Click to expand.
2
of 2 votes

Aren't you performing a O(log N) operation N times? I would think this solution is O(N log N)

- Gabe October 19, 2013 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

It's also interesting that the sorted nature of the matrix is irrelevant to this approach - which appears to be O(n log n) regardless of the input.

- Michael.J.Keating October 19, 2013 | Flag
Comment hidden because of low score. Click to expand.
-2
of 2 vote

I got the solution in O(n). Do verify and let me know

import java.io.*;
import java.util.Scanner;

class arraysort2d
{
 public int n;
 public int irows, jrows,icols,jcols;
  
public static void main(String args[])
{
  arraysort2d obj = new arraysort2d();
  obj.input_array(); 
}

public int get_input()
{
  Scanner input = new Scanner(System.in);
  String answer = input.nextLine();
  return(Integer.parseInt(answer));
}

public void input_array()
{
  int i,j,count = 0, rval = 0;
  System.out.println("Input the value of N   ");
  n = get_input();
  System.out.println(" Value of N   " + n);
  int arr[][] = new int [n][n];
  int array1d[] = new int[n*n];
  
  System.out.println("Input the array  ");
   for (i = 0; i < n; i ++)
   {
     for (j = 0; j < n; j ++)
	 {
	   arr[i][j] = get_input();
	 }
   }
   
    System.out.println(" The array is   ");
	for (i = 0; i < n; i ++)
   {
     for (j = 0; j < n; j ++)
	 {
	   System.out.print(" " + arr[i][j]) ;
	 }
	   System.out.print("\n");
   }
  // ------------ Computation starts----------------------- 
   irows = 0;
   jrows = 1;
   icols = 1;
   jcols = 0;
   array1d[rval++] = arr[0][0];
   
   while(++count < n * n)
   {
     if (arr[irows][jrows] < arr[icols][jcols])
	 {
	   array1d[rval++] = arr[irows][jrows];
	   if(jrows == n-1)
	   {
	    if(icols == n-1)
	      jrows = n-1;
		else
		  jrows = 1;
		
		irows += 1;
	   }
	   else
	    jrows ++;
	 }
	 else
	 {
	   array1d[rval++] = arr[icols][jcols];
	   if(icols == n-1)
	   {
	     if(jrows == n-1)
	       icols = n-1;
	     else
		   icols = 1;
	
		 jcols +=1;
	   }
	   else
	     icols ++;	   
	 }
   }
   System.out.print(" " + count + " " + rval + "\n");
   array1d[--rval] = arr[n-1][n-1];
   
 //---------- Computation ends -------------
   
   for ( i = 0; i < n*n; i ++)
    {
	  System.out.print(" " + array1d[i]);
	}
   
}
 
}

- omega1991 October 20, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

There is no solution faster that O(n^2 * Log n) where n - is the size of matrix.

Check you solution on something like this:

a a a a b
a a a b c
a a b c c
a b c c c
b c c c c

Where
a - different values in range (x1, x2)
b - different values in range (x2+1, x3 - 1)
c - different values in range (x3, x4)

I mean, all values upper diagonal is less than diagonal. And all values then down than diagonal - is more than diagonal.

- Darida October 20, 2013 | Flag
Comment hidden because of low score. Click to expand.
Comment hidden because of low score. Click to expand.
-2
of 2 votes

struct item {
int ele;
int i;
int j;
item(int ele_, int i_, int j_) { i = i_ ; j = j_ ; ele = ele_ ; }
// for min heap in c++, u need to right this comparator
bool operator<(const item& other)
{
return ele > other.ele;
}
};
vector<int> convert(const vector< vector<int> >& a, int n)
{
assert(a.size() == n && a[0].size() == n);

priority_queue<item> pq;
vector< vector<bool> > visit(n, vector<bool>(n, false));
vector<int> ans;

int i(0), j(0);
if (n > 0) pq.push( item(a[i][j], i, j) );
while (!pq.empty())
{
item it = pq.top(); pq.pop();
ans.push_back(it.ele);
if (it.i + 1 < n && !visit[it.i+1][it.j]) {
ans.push( item(a[it.i+1][it.j], it.i+1, it.j) );
visit[it.i+1][it.j] = true;
}
if (it.j + 1 < n && !visit[it.i][it.j+1] ) {
ans.push( item(a[it.i][it.j+1], it.i. it.j+1) );
visit[it.i][it.j+1] = true;
}
}
return ans;
}

- Anonymous October 19, 2013 | Flag
Comment hidden because of low score. Click to expand.
Comment hidden because of low score. Click to expand.
-1
of 1 vote

1) O(N*N) worst case for any solution? Huh? You mean OMEGA(N*N) ?

2) Merge sort which runs in O(N* Log N)
-> In this problem N is a dimension of the square matrix. So M.Sort is O(N^2 lgN)

3) With this approach, the space efficiency is O(1) and the time efficiency is O(1/4 * N*N).
-> What does this mean? What is the "1/4" for? You break the square matrix up into 4 element blocks (with two outer for loops). But then you have inner for loops to work on each for 4 elements per block. You aren't magically touching only 1/4 the elements.

4) Have you tested this? How could this possibly work? Looks like you'd have to sort "sorted_array" at the end for it to be really sorted (correct me if I'm wrong).



For the problem itself, we have global upper and lower bounds on any optimal solution in terms of time complexity:

1) Upperbound O(N^2 lgN) <--- Because the original poster's mergesort does this

2) Lowerbound Omega(N^2) <-- Gotta touch them all. In fact, it can't be C <1 constant within the O either.

- S O U N D W A V E October 19, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 2 votes

You edited your original post :) Cool.

- S O U N D W A V E October 19, 2013 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

Since the matrix has O(n*n) elements thus the merge sort will take O(n^2 log n^2) = O(2*n^2 log n) time. Though it is true that O(n*n) is the asymptotic lower bound, but I doubt if the problem can be solved in O(n*n) time unless some special cases or some restrictions on input are given.

- EOF October 19, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@EOF

True. I can see a solution that might be N^2 with high probability (or avg. case N^2 maybe, or at the very least N^2 best case) but can't think of an N^2 worst case.

The matrix is already (from top left) in a min-heap form (but with a stronger rep. invariant property, with subtrees overlapping unlike a usual min-heap).

We can create a separate min-heap, put the (0,0) element then loop on max_extract's and inserting children of everything we extracted (but we can also use the extra overlapping properly to exclude certain children from needing to be inserted into the min. heap).

The size of the aux. min. heap is "usually" rather small on the average case (and in the best case it should be small and independent of N, making the whole alg. N^2 in best case).

- S O U N D W A V E October 19, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

loop in MIN-extracts*

- S O U N D W A V E October 19, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Children of a node in the matrix would be defined as:

LEFT(i, j ) = A[i+1,j]
RIGHT(i, j ) = A[i, j+1]

Node, the matrix is a kind of quasi-min-heap to begin with:
1) A[0,0] - top left - is the minimum of all elements
2) Every node A[i,j] is < LEFT, RIGHT children (as defined above) 

So we can create an aux. min. heap, 
store (0,0) in there, then:

while( aux.min.heap not empty)
{
    x=extractMinAux;
    storeInResultArray(x);
    insertMinAux( children of x THAT are not descendents of elements already in aux.min heap <--- this bit is special for this quasi min heap );
}

return result array

- S O U N D W A V E October 19, 2013 | Flag


Add a Comment
Name:

Writing Code? Surround your code with {{{ and }}} to preserve whitespace.

Books

is a comprehensive book on getting a job at a top tech company, while focuses on dev interviews and does this for PMs.

Learn More

Videos

CareerCup's interview videos give you a real-life look at technical interviews. In these unscripted videos, watch how other candidates handle tough questions and how the interviewer thinks about their performance.

Learn More

Resume Review

Most engineers make critical mistakes on their resumes -- we can fix your resume with our custom resume review service. And, we use fellow engineers as our resume reviewers, so you can be sure that we "get" what you're saying.

Learn More

Mock Interviews

Our Mock Interviews will be conducted "in character" just like a real interview, and can focus on whatever topics you want. All our interviewers have worked for Microsoft, Google or Amazon, you know you'll get a true-to-life experience.

Learn More