简体   繁体   中英

Order array such that all positive numbers appear first

i am writing a code in c# to sort an array, i want all the negative values in the right side and all the positive values in the left side, the should not be in decreasing order

namespace SortApp
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] newInt = new int[] { 5, -2, -1, -4, -20, 6, 7, -14, 15, -16, 8, 9, 10 };
            int size = 12, i= 0;             // or newInt.Length

            for (i = 0; i < newInt.Length; i++)
            {
                if (newInt[i] < 0 && newInt[size] > 0)
                {
                    int temp = newInt[i];
                    newInt[i] = newInt[size];
                    newInt[size] = temp;
                    size--;
                }
            }
            for (i = 0; i < newInt.Length; i++)
            {
                Console.Write(newInt[i]);
                Console.Write(" ");
            }
        }
    }
}

but the output is something like this (-20 is on wrong side):

5 10 9 8 -20 6 7 -14 15 -16 -4 -1 -2

but the intended output is:

5 10 9 8 15 6 7 -14 -20 -16 -4 -1 -2 

Why is my code not producing my intended output?

Your solution incorrectly decides when to finish the loop. Also, it unconditionally increments i in the loop header, and never decrements size even when it points to a negative number.

Here is how you fix it:

for (i = 0; i < size ; ) {
    if (newInt[i] < 0 && newInt[size] >= 0) {
        int temp = newInt[i];
        newInt[i] = newInt[size];
        newInt[size] = temp;
        size--;
        i++;
        continue;
    }
    if (newInt[i] >= 0) {
        i++;
    }
    if (newInt[size] < 0) {
        size--;
    }
}

Here is a demo on ideone .

You can rewrite this loop using a more readable identifiers for your left and right pointers, rather than using i and size . This would make your algorithm look more "symmetric" in the code, to recognize the symmetry in its design:

int left = 0, right = newInt.Length-1;
while (left < right) {
    if (newInt[left] < 0 && newInt[right] >= 0) {
        int temp = newInt[left];
        newInt[left] = newInt[right];
        newInt[right] = temp;
        right--;
        left++;
        continue;
    }
    if (newInt[left] >= 0) {
        left++;
    }
    if (newInt[right] < 0) {
        right--;
    }
}

Here is an ideone link to the alternative implementation .

Try this solution:

var newInt = new[] {5, -2, -1, -4, -20, 6, 7, -14, 15, -16, 8, 9, 10};
var solution = newInt.GroupBy(i => i > 0).
    SelectMany(g => g).
    ToArray();

The problem with your algorithm is that when you decrease size , you end up having newInt[size] point at a negative value, and the if block is not entered.

The general idea for a pretty easy easy solution would be to start one index, call it left at the beginning of the array, and another, called right at the end of the array.

Increment left until you find a negative number, or until left == right . When you hit a negative number, decrement right until you find a positive number, or until right == left .

If left is indexing a negative number and right is indexing a positive number, swap the two items and start incrementing left again.

The general idea, not tested:

int left = 0;
int right = a.Length-1;
while (left < right)
{
    if (a[left] < 0)
    {
        while (right > left)
        {
            if (a[right] >= 0)
            {
                // swap here
                int temp = a[left];
                a[left] = a[right];
                a[right] = temp;
                break;
             }
             --right;
        }
    }
    ++left;
}

This yields the desired order with a minimum of loops

int[] newInt = new int[] { 5, -2, -1, -4, -20, 6, 7, -14, 15, -16, 8, 9, 10 };
int lt = 0;
int rt = newInt.Length - 1;
while (true) {
    // Find first negative number
    while (newInt[lt] >= 0 && lt < rt) {
        lt++;
    }

    // Find last positive number
    while (newInt[rt] < 0 && rt > lt) {
        rt--;
    }

    if (lt == rt) {
        break; // Finished
    }

    // Swap
    int temp = newInt[lt];
    newInt[lt] = newInt[rt];
    newInt[rt] = temp;
}
//TODO: Print result

if you can use generics and linq than the easiest solution would be :

int[] newInt = new int[] { 5, -2, -1, -4, -20, 6, 7, -14, 15, -16, 8, 9, 10 };
newInt.ToList().Sort();
newInt.Reverse();
newInt = newInt.ToArray();

Hope this will help !!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM