Given an array of positive and negative integers, re-arrange it so that you have positive integers on one end and negative integers on other

后端 未结 30 2515
醉梦人生
醉梦人生 2020-12-07 07:37

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

相关标签:
30条回答
  • 2020-12-07 08:39

    I'm not sure I understand the question correctly, as the answer appears to be too simple:

    • Walk through the array and count negative numbers - O(n)
    • Create a new array of size O(n)
    • Walk through original array and place numbers into the new array. Use the known number of negative numbers to offset the positive ones - O(n)

    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:

    • Start from the leftmost negative number. Walk through the array until you find the next negative number.
    • In a new loop, exchange the negative number with the positive number left of it. Do this until you reach the other negative numbers. This ensures the order of the numbers remains unchanged.
    • Rince and repeat until you reach the end of the array when looking for a new negative number.
    0 讨论(0)
  • 2020-12-07 08:39

    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.

    • In the first scan, find # of negative and positive values, and the max.
    • In the second scan we create the negative section of array as follows:

    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].

    • In the third scan, we create the positive section of array. by end of the second scan, the negative array is constructed, and the positive numbers are shifted to the right side, but their location may not be correct. So we go though it and correct their position since this info was encoded their value.

    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;
        }
    
    }
    
    0 讨论(0)
  • 2020-12-07 08:39

    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.

    0 讨论(0)
  • 2020-12-07 08:39

    Look at Heapsort in the table of sorting algorithms on Wikipedia: http://en.wikipedia.org/wiki/Sorting_algorithm

    0 讨论(0)
  • 2020-12-07 08:40

    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.

    0 讨论(0)
  • 2020-12-07 08:40

    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

    0 讨论(0)
提交回复
热议问题