Place positive numbers before negative

半城伤御伤魂 提交于 2021-02-17 05:13:05

问题


So I have this code which I found on the internet which takes an array of negative and positive numbers and rearranges the array so all negative numbers are before the positive ones. But the position of appearance of each number has to remain the same. So for example if i have -2 5 -9 ....., in the organized array -2 still has to be the first number of the negative ones and -9 has to be the second of the negative ones, also 5 has to be the first number of the positive ones.

Example:

Input: {1,7,-5,9,-12,15,-6,-8}
Output:{-5,-12,-6,-8,1,7,9,15}

So the code is working correctly but what I want to do is to change it so positive numbers appear before the negative ones.

Example:

Input: {1,7,-5,9,-12,15,-6,-8}
Output:{1,7,9,15,-5,-12,-6,-8}

Here's the code please if you can help me, I know that it's not very complicated but I can't figure it out.

// Java program to Rearrange positive and negative
// numbers in a array
public class Rearrangement {
    /* Function to print an array */
    static void printArray(int[] A, int size) {
        for (int i = 0; i < size; i++)
            System.out.print(A[i] + " ");
        System.out.println("");
    }

    /* Function to reverse an array. An array can be
    reversed in O(n) time and O(1) space. */
    static void reverse(int[] arr, int l, int r) {
        if (l < r) {
            arr = swap(arr, l, r);
            reverse(arr, ++l, --r);
        }
    }

    // Merges two subarrays of arr[].
    // First subarray is arr[l..m]
    // Second subarray is arr[m+1..r]
    static void merge(int[] arr, int l, int m, int r) {
        int i = l; // Initial index of 1st subarray
        int j = m + 1; // Initial index of IInd

        while (i <= m && arr[i] < 0)
            i++;
        // arr[i..m] is positive
        while (j <= r && arr[j] < 0)
            j++;
        // arr[j..r] is positive

        // reverse positive part of
        // left sub-array (arr[i..m])
        reverse(arr, i, m);

        // reverse negative part of
        // right sub-array (arr[m+1..j-1])
        reverse(arr, m + 1, j - 1);

        // reverse arr[i..j-1]
        reverse(arr, i, j - 1);
    }

    // Function to Rearrange positive and negative
    // numbers in a array
    static void RearrangePosNeg(int[] arr, int l, int r) {
        if (l < r) {
            // Same as (l+r)/2, but avoids overflow for
            // large l and h
            int m = (l + r) / 2;

            // Sort first and second halves
            RearrangePosNeg(arr, l, m);
            RearrangePosNeg(arr, m + 1, r);

            merge(arr, l, m, r);
        }
    }

    static int[] swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
        return arr;
    }

    public static void main(String[] args) {
        int[] arr = {1, 7, -5, 9, -12, 15, -6, -8};
        int arr_size = arr.length;
        RearrangePosNeg(arr, 0, arr_size - 1);
        printArray(arr, arr_size);
    }
}

回答1:


Existing solution may be easily parameterized by adding a Predicate<Integer> argument to methods rearrangePosNeg and merge and depending on this argument the positive or negative values will be placed at the beginning of the array:

static void rearrangePosNeg(int[] arr, int l, int r, Predicate<Integer> p) {
    if (l < r) {
        // Same as (l+r)/2, but avoids overflow for large l and r
        int m = l - (l - r)/2;

        // Sort first and second halves
        rearrangePosNeg(arr, l, m, p);
        rearrangePosNeg(arr, m + 1, r, p);

        merge(arr, l, m, r, p);
    }
}

static void merge(int[] arr, int l, int m, int r, Predicate<Integer> p) {
    int i = l; // Initial index of 1st subarray
    int j = m + 1; // Initial index of IInd

    while (i <= m && p.test(arr[i])) i++;
    while (j <= r && p.test(arr[j])) j++;

    reverse(arr, i, m);

    reverse(arr, m + 1, j - 1);

    reverse(arr, i, j - 1);
}

Then the rearrangePosNeg method can be invoked:

int[] arr = {1,7,-5,9,-12,15,-6,-8};
int arr_size = arr.length;
rearrangePosNeg(arr, 0, arr_size - 1, (x) -> x > 0); // put positives first
printArray(arr, arr_size);

Output:

1 7 9 15 -5 -12 -6 -8 

Also, a simpler iterative solution using a new array and a couple of indexes is possible:

static int[] rearrange(int[] arr, Predicate<Integer> p) {
    int n = arr.length;
    int[] rearranged = new int[n--];

    for (int i = 0, iFirst = 0, iLast = n; i <= n; i++) {
        if (p.test(arr[i])) {
            rearranged[iFirst++] = arr[i]; // copying by condition to the head
        }
        if (!p.test(arr[n - i])) {
            rearranged[iLast--] = arr[n - i]; // copying opposite to the tail
        }
    }
    return rearranged;
}

Test:

int[] arr = {1,7,-5,9,-12,15,-6,-8};

System.out.println("iterative: " +  Arrays.toString(rearrange(arr, (x) -> x > 0)));

Output:

iterative: [1, 7, 9, 15, -5, -12, -6, -8]

Update

Without the Predicate parameter, the condition in merge function needs to be inverted:

static void rearrangePosNeg(int[] arr, int l, int r) {
    if (l < r) {
        // Same as (l+r)/2, but avoids overflow for large l and r
        int m = l - (l - r)/2;

        // Sort first and second halves
        rearrangePosNeg(arr, l, m);
        rearrangePosNeg(arr, m + 1, r);

        merge(arr, l, m, r);
    }
}

static void merge(int[] arr, int l, int m, int r) {
    int i = l; // Initial index of 1st subarray
    int j = m + 1; // Initial index of IInd

    while (i <= m && arr[i] > 0) i++;
    while (j <= r && arr[j] > 0) j++;

    reverse(arr, i, m);

    reverse(arr, m + 1, j - 1);

    reverse(arr, i, j - 1);
}



回答2:


You can filter two substreams from this array: positive and negative, and then concat them. This greatly simplifies your code:

public static void main(String[] args) {
    int[] arr = {1, 7, -5, 9, -12, 15, -6, -8};

    System.out.println(Arrays.toString(rearrangePosNeg(arr)));
    // [-5, -12, -6, -8, 1, 7, 9, 15]
}
public static int[] rearrangePosNeg(int[] arr) {
    return IntStream.concat(
            Arrays.stream(arr) // negative
                    .filter(i -> i < 0),
            Arrays.stream(arr) // positive
                    .filter(i -> i >= 0))
            .toArray();
}

If you want to swap the positive and negative substreams, you can swap the parts of the filters: i < 0 and i >= 0.


See also: Rotating an int Array in Java using only one semicolon



来源:https://stackoverflow.com/questions/66145933/place-positive-numbers-before-negative

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!