【问题标题】:Arrange all elements of a n-sized array so that the output array has all negative elements first, then zeros and the the positive ones without sorting排列 n 大小数组的所有元素,使输出数组首先具有所有负元素,然后是零和正元素而不进行排序
【发布时间】:2018-09-02 22:52:12
【问题描述】:

给定一个大小为n 的数组,我想对元素进行排列,以便输出返回该数组首先包含所有负元素,然后是零,最后是所有正元素,而不对数组进行排序。也就是说,我想将数组分成 3 部分,得到复杂度 O(n) 并且不使用额外的数组。

下面的代码是一个尝试,但它对数组进行排序,这不是我想要的,因为即使优化它我也只能达到时间复杂度O(nlogn)。

using System;

public class sort
{
public static void Main(string[] args)
{
    int n, k, t;
    Console.WriteLine("Enter the size of array");
    n = Convert.ToInt32(Console.ReadLine());
    int[] arr = new int[n];
    for (k = 0; k < n; k++)
    {
        Console.Write("\nEnter your number:\t");
        arr[k] = Convert.ToInt32(Console.ReadLine());
    }

    for (int j = 0; j <= n- 2; j++)
    {
        for (int i = 0; i <= n - 2; i++)
        {
            if (arr[i] > arr[i + 1])
            {
                t = arr[i + 1];
                arr[i + 1] = arr[i];
                arr[i] = t;
            }
        }
    }
    Console.WriteLine("The output array :");
    foreach (int aray in arr)
        Console.Write(aray + " ");
        Console.ReadLine();
}
}

提前感谢您的建议。

【问题讨论】:

标签: arrays algorithm dynamic-programming partitioning


【解决方案1】:

可以通过取另一个数组来完成。设另一个数组为 b
首先,我们遍历初始数组并将负数存储在数组b中。然后,我们再次遍历初始数组并将零值存储在数组 b 中。这样,数组 b 中的负数之后会出现零,因为数组 b 中最后一个数字的索引保存在另一个变量 j时间>。现在,我们再次遍历初始数组并将正数存储在数组 b 中。这样,如果我们输出数组 b 的元素,我们将首先得到所有负元素,然后是零,最后是所有正元素。

下面的代码正是这样做的:

using System;

public class sort
{
public static void Main(string[] args)
{
    int n, k, i, t, j=0;
    Console.WriteLine("Enter the size of array");
    n = Convert.ToInt32(Console.ReadLine());
    int[] arr = new int[n];
    int[] b = new int[n];
    for (k = 0; k < n; k++)
    {
        Console.Write("\nEnter your number:\t");
        arr[k] = Convert.ToInt32(Console.ReadLine());
    }
    for(i = 0; i < n; i++){
       if(arr[i] < 0)
         {b[j] = arr[i]; j++;}
       }
    for(i = 0; i < n; i++){
       if(arr[i] == 0)
         {b[j] = arr[i]; j++;}
       }
    for(i = 0; i < n; i++){
       if(arr[i] > 0)
         {b[j] = arr[i]; j++;}
       }

    Console.WriteLine("The output array :");
    foreach (int aray in b)
        Console.Write(aray + " ");
        Console.ReadLine();
}
}

三个循环的时间复杂度均为 O(n)

【讨论】:

  • 我不确定 OP 是否想要这样,我认为 O(n) 意味着即使我知道您的代码也是 O(n),他只对数组进行一次迭代。更好的是动态编程和额外的内存,这样单次迭代就可以了。
  • @kuskmen 完全正确!此外,我想使用相同的数组,而不创建新数组。
  • 因此,您希望通过一次迭代和 n 次交换以结束 [负数、零数、正数] 场景.. 嗯,我不确定这应该如何完成,但我很想看看:)
  • 正确!我也在尝试,但我无法弄清楚
  • 我对这个问题有一些疑问,但我无法发表评论,因为我没有足够的声誉。很抱歉误解了这个问题。
【解决方案2】:

感谢 m69 的建议。这是 C# 中实现 Dijkstra 的 3 分区的正确代码:

using System;
using System.Diagnostics;

public class Program
{
    public static void Main()
    {
        int[] array1 = {1, -3, 5, 7, -9, 0, 2, -4, 6, 8, 0}; 
        printArray(partitioning(array1, 0));
    }

    public static int[] partitioning(int[] array, int mid)
    {
        int i = 0, j = 0, n = array.Length;
        Trace.Assert(n > 0);
        while (j < n)
        {
            if (array[j] < mid)
            {
                swap(ref array[i], ref array[j]);
                i += 1;
                j += 1;
            }
            else if (array[j] > mid)
            {
                swap(ref array[j], ref array[n-1]);
                n -= 1;
            }
            else 
                j += 1;
        }

        //Time complexity: O(n)
        return array;
    }

    public static void printArray(int[] array)
    {
        for(int i=0; i<array.Length; ++i) {
            Console.Write("" + array[i] + " ");
        }
        Console.WriteLine("");
    }

    public static void swap(ref int a, ref int b)
    {
        int temp = a;
        a = b;
        b = temp;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-06
    • 2014-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多