简体   繁体   中英

How to sort ascending only odd numbers in array?

I want to sort only odd numbers without moving even numbers. For example, if my input is:

[5, 3, 2, 8, 1, 4]

The expected result is:

[1, 3, 2, 8, 5, 4]

I am new to C# and I came across a challenge on the Internet that has me perplexed. I have tried for hours and I would like to learn this concept in

The challenge states:

You have an array of numbers. Your task is to sort ascending odd numbers but even numbers must be on their places. Zero isn't an odd number and you don't need to move it. If you have an empty array, you need to return it.

Here is my code so far, please take it easy on me I am in the beginning stages of programming.

public static int[] SortArray(int[] array)
{
    var dict = new Dictionary<int, int>();
    var dict2 = new Dictionary<int, int>();

    for (int i = 0; i < array.Length; i++)
    {
        int j =0;
        if (array[i] % 2 != 0)
        {
            dict.Add(array[i], i+1);
        }
        else
        {
            dict2.Add(array[i], i+1);
        }
    }
    var result = dict.OrderBy(x => x.Key);
    Dictionary<int, int> resultDic = result.Union(dict2)
      .GroupBy(x => x.Key).ToDictionary(o => o.Key, o => o.Key);
}

public static void Main()
{
    SortArray(new int[] { 5, 3, 2, 8, 1, 4});
}

Check this code. Explanations added as comments

public static int[] SortArray(int[] array)
{
    //temp variable for holding larger value for switching
    int temp = 0;

    for (int i = 0; i < array.Length; i++)
    {
        //If the value is 'even' continue with outer loop
        if(array[i] % 2 == 0)
           continue;

        //Inner loop to compare array values
        for(int j = (i + 1); j < array.Length; j++)
        {
            //If this value is not even do comparison
            if(array[j] % 2 != 0)
            {
                //If the left value is greater than the right value
                //swap them
                if(array[i] > array[j])
                {
                   temp = array[i];
                   array[i] = array[j];
                   array[j] = temp;
                }
            }
        }
    }

    return array;
}

public static void Main()
{
    SortArray(new int[] { 5, 3, 2, 8, 1, 4});
}

You can do this with linq by indexing the numbers before you start:

var nums = new[] { 5, 3, 2, 8, 1, 4 };
var indexedNums = nums.Select((num, idx) => new { num, idx }).ToList();

Then sorting these indexed numbers into evens and odds:

var evens = indexedNums.Where(x => x.num % 2 == 0);
var odds = indexedNums.Where(x => x.num % 2 == 1);

Sorting the odd (indexed) numbers by their value:

var sortedOdds = odds.OrderBy(x => x.num); //sort the odd numbers by their value

Zipping this sequence with the odds sequence (which is sorted by index), taking the number from sortedOdds and the index from odds

var reindexedOdds = sortedOdds.Zip(odds, (o1, o2) => new { o1.num, o2.idx });

...and throwing these reindexedOdds into a sequence with the indexed evens from above, sorting by index and then selecting out the number.

var endSequence = evens.Concat(reindexedOdds).OrderBy(x => x.idx).Select(x => x.num);

While the other solutions are formally correct, most of them are not efficient, being with O(n^2) time complexity.

Another (and more time efficient) approach should imply the use of two lists: the first will contain the indexes of odd numbers, and the second will store the sorted odd numbers.

public static int[] SortArray(int[] array)
{
    var sortedOdds = new List<int>(array.Length);
    var oddsIndexes = new List<int>(array.Length);
    var newArray = new int[array.Length];

    for(var i = 0; i < array.Length; i++) // O(n)
    {
        var value = array[i];
        if(value % 2 == 1)
        {
            sortedOdds.Add(value);
            oddsIndexes.Add(i);
        } else
        {
            newArray[i] = value;
        }
    }

    sortedOdds.Sort(); // average complexity O(n log n)

    for(var j = 0; j < sortedOdds.Count; j++) // O(n)
    {
        var value = sortedOdds[j];
        var index = oddsIndexes[j];
        newArray[index] = value;
    }

    return newArray;
}

This will reduce the complexity to an average of O(n log n) time.

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