I recently came across a Microsoft Interview Question for Software Engineer.
Given an array of positive and negative integers, re-arrange it so that you
I'm not sure I understand the question correctly, as the answer appears to be too simple:
Here's a quick way to do it in Python. It slightly differs from the above in first creating an array for the negatives, then appending the positives. So it's not as efficient, but still O(n).
>>> a = [1,7,-5,9,-12,15]
>>> print [x for x in a if x < 0] + [y for y in a if y >= 0]
[-5, -12, 1, 7, 9, 15]
Edit: Ok, now with O(1) space compexity it gets much harder. I'm interested in how to achieve it in O(n) time complexity, too. If it helps, here's a way to keep the O(1) space complexity, but requires O(n^2) time complexity:
It can be done in O(n) and space O(1).
We need to scan 3 times through the array and change some values carefully.
Assumption: the max value in the array with size N is should be smaller than (N+1) * Integer.MAX_VALUE
.
We need this assumption since we well change some positive values in the array.
We start from the beginning of the array and we "swap" the first found positive number (e.g. at index i
) with the first found negative number (e.g. j
). Since negative numbers are being considered with respect to their location, the swap will be okay.
The problem is the positive numbers because there might be some other positive numbers between i
and j
. To handle this issue, we have to somehow encode the index of the positive number in that value before swapping. So then we can realize where it was at the first point. We can do this by a[i]=(i+1)*(max)+a[i]
.
Here is the code:
import java.util.Arrays;
public class LinearShifting {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] a = {-1,7,3,-5,4,-3,1,2};
sort(a);
System.out.println(Arrays.toString(a)); //output: [-1, -5, -3, 7, 3, 4, 1, 2]
}
public static void sort(int[] a){
int pos = 0;
int neg = 0;
int i,j;
int max = Integer.MIN_VALUE;
for(i=0; i<a.length; i++){
if(a[i]<0) neg++;
else pos++;
if(a[i]>max) max = a[i];
}
max++;
if(neg==0 || pos == 0) return;//already sorted
i=0;
j=1;
while(true){
while(i<=neg && a[i]<0) i++;
while(j<a.length && a[j]>=0) j++;
if(i>neg || j>=a.length) break;
a[i]+= max*(i+1);
swap(a,i,j);
}
i = a.length-1;
while(i>=neg){
int div = a[i]/max;
if(div == 0) i--;
else{
a[i]%=max;
swap(a,i,neg+div-2);// minus 2 since a[i]+= max*(i+1);
}
}
}
private static void swap(int[] a, int i , int j){
int t = a[i];
a[i] = a[j];
a[j] = t;
}
}
Here's a solution with only 2 iterations:
Let's say the length is n.
And i'll use C like code, ignore syntax errors.
solution[n];
for (i= 0,j=0 ; i < n ; i++ ) {
if (array[i] < 0) solution[j++] = array[i];
}
for (i = n-1,j=n-1 ; ; i > 0 ; i--) {
if (array[i] >= 0) solution[j--] = array[i];
}
The idea is to go over it once, and write all the negatives we encounter.
Then go over it the second time from the end, and write the positives from the end towards the beginning.
Look at Heapsort in the table of sorting algorithms on Wikipedia: http://en.wikipedia.org/wiki/Sorting_algorithm
If the goal is O(1) space (besides the elements themselves, which are assumed to be freely mutable) and O(NlgN) time, divide the problem into that of arranging arrays that are known to be of the form pnPN, where p and P represents zero or more positive numbers and n and N represents 0 or more negative numbers, into arrays of the form pPnN. Any two-element array will automatically be of that form. Given two arrays of that form, locate the first negative number, next positive number, and last positive number, and "spin" the middle two sections of the array (easy to do in constant space, and time proportional to the size of the array to be 'spun'). The result will be an array of the form pPnN. Two consecutive such arrays will form a larger array of the form pnPN.
To do things in constant space, start by pairing up all elements and putting them into PN form. Then do all quartets of elements, then all octets, etc. up to the total size of the array.
This can simply be done by following steps in O(n), without using any extra space
int count = 0;
//data is the array/vector in sort container having given input.
if(data[0] < 0)
count++;
for(int i = 1; i < n; i++)
{
if(data[i] < 0)
{
int j = i;
while(j> count)
{
data[j-1] += data[j];
data[j] = (data[j-1]-data[j]);
data[j-1] -= data[j];
j--;
}
count++;
}
}
it's complete implementation can be found here https://gist.github.com/Shravan40/8659568