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
O(n) solution Java
private static void rearrange(int[] arr) {
int pos=0,end_pos=-1;
for (int i=0;i<=arr.length-1;i++){
end_pos=i;
if (arr[i] <=0){
int temp_ptr=end_pos-1;
while(end_pos>pos){
int temp = arr[end_pos];
arr[end_pos]=arr[temp_ptr];
arr[temp_ptr]=temp;
end_pos--;
temp_ptr--;
}
pos++;
}
}
I have hard-coded the values of the array. However it will work any set of integers.
int[] n={2,-3,1,5,-10,-8};
int k=0;
for(int i=1;i<n.length;i++)
{
int temp=0;
if(n[i]<0)
{
temp=n[k];
n[k]=n[i];
n[i]=temp;
k++;
}
}
for(int j=0;j<n.length;j++)
{
System.out.println(n[j]);
}
I think this would work: Here's a simple way that's constant space (but quadratic time). Say the array is length N. Walk along the array from i = 0 to i = N-2 checking element i and i+1. If element i is positive and element i+1 is negative, swap them. Then repeat that process.
Each pass across the array will make the negatives drift to the left (and positives drift to the right), sort of like a bubble sort, until (after sufficient number of passes) they are all in their correct place.
Also, I think this would work: It's also constant space (but quadratic time). Say P is the number of positives. Scan from left to right, when you find a positive x stop the scan, and "delete it" by shifting all the items after it left by one. Then put x at the end of the array. Repeat procedure scan P times to move every positive.
An extremely simple solution is below but not in O(n). I changed the insertion sort algorithm a bit. Instead of checking if a number is greater or smaller, it checks if they are greater or less than zero.
int main() {
int arr[] = {1,-2,3,4,-5,1,-9,2};
int j,temp,size;
size = 8;
for (int i = 0; i <size ; i++){
j = i;
//Positive left, negative right
//To get opposite, change it to: (arr[j] < 0) && (arr[j-1] > 0)
while ((j > 0) && (arr[j] >0) && (arr[j-1] < 0)){
temp = arr[j];
arr[j] = arr[j-1];
arr[j-1] = temp;
j--;
}
}
//Printing
for(int i=0;i<size;i++){
cout<<arr[i]<<" ";
}
return 0;
}
Here is my solution in Python, using recursion (I had an assignment like this, where the array should be sorted relatively to a number K. If You put K = 0, You've got Your solution, without retaining the order of appearance):
def kPart(s, k):
if len(s) == 1:
return s
else:
if s[0] > k:
return kPart(s[1:], k) + [s[0]]
else:
return [s[0]] + kPart(s[1:], k)
Edit (5/29/2015): I overlooked the requirement for maintaining order of appearance, so the answer below does not satisfy all of the requirements of the question. However, I leave the original response up for general interest.
This is a special version of a very important subroutine of quicksort known as "partition." Definition: an array A having N numeric entries is partitioned about value K at index p if A[i] < K for 0 <= i < p and A[j] >= K for p <= j < N, unless all the entries are less than K (meaning p = N) or not less than K (meaning p = 0). For the problem in question, we will partition the array around K = 0.
You can partition an unsorted array about any value K in O(n) time, accessing each entry in the array just once, using O(1) additional memory. Informally, you step through the array from both ends, moving values that are on the wrong side. Perform a swap when one misplaced value is found on each side of the array, then continuing stepping inward. Now the C++ code:
// Assume array A[] has size N
int K = 0; // For particular example partitioning positive and negative numbers
int i = 0, j = N-1; // position markers, start at first and last entries
while(1) { // Break condition inside loop
while(i < N && A[i] < K) i++; // Increase i until A[i] >= K
while(j >= 0 && A[j] >= K) j--; // Decrease j until A[j] < K
if(i < j)
swap(A[i],A[j]);
else
break;
}
// A[] is now partitioned, A[0]...A[j] < K, unless i==0 (meaning all entries >= K).
Note that if all elements are equal to K (zero in this case), i is never incremented and j = 0 at the end. The problem statement assumes this will never happen. Partition is very fast and efficient, and this efficiency is the reason why quicksort is the most popular sorting routine for large arrays. The swap function can be std::swap in C++ or you can easily write your own:
void swap(int& a, int& b) {
int temp = a;
a = b;
b = temp;
}
Or just for fun, numbers can be swapped in place with no temporary memory, though be mindful of overflow:
// This code swaps a and b with no extra space. Watch out for overflow!
a -= b;
b += a;
a = b - a;
There are many variations to partition for special cases, such as a three way partition for [elements < K] [elements == K] [elements > K]. The quicksort algorithm calls partition recursively, and the partition value K is usually the first entry in the current sub-array or computed from a few entries (such as median of three). See textbooks: Algorithms by Sedgewick and Wayne (4th ed., p. 288) or The Art of Computer Programming Vol. 3 by Knuth (2nd ed., p. 113).