【问题标题】:Place all distinct elements of the array to the left in C#在 C# 中将数组的所有不同元素放在左侧
【发布时间】:2018-03-29 06:31:34
【问题描述】:

我正在尝试编写一个程序,将数组的所有不同元素放在同一个数组的左侧,然后以任何顺序将所有其他(非不同)元素放在后面。时间复杂度必须是 O(n log n),即使用排序并且不必创建额外的数组。我尝试使用以下代码打印不同的元素:

using System;  
using System.Diagnostics;
public class Program
{  
    public static void Main() 
    {
      int []arr = {1, 1, 6, 5, 4, 3, 4, 6, 1, 7, 2, 1, 4, 9};
      allDistinct(arr);
    }

     public static void allDistinct(int[] x)
     {
          int n = x.Length;
          Trace.Assert(n>0);

          Array.Sort(x); //O(n log n)

          for (int i = 0; i < n; i++)
          {
               // Move the index ahead while 
               // there are duplicates
               while (i < n - 1 && x[i] == x[i + 1])
                    i++;
          }
          Console.WriteLine(x[i]);
    }
}

但是,我希望我的函数具有以下形式

public static int[] allDistinct(int[] x)

然后在Main()中使用辅助函数打印数组

printArray(allDistinct(arr));

在哪里

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

我尝试使用交换函数,但没有成功得到我想要的,即给定数组

1 1 6 5 4 3 4 6 1 7 2 1 4 9

我的输出应该是

1 2 3 4 5 6 7 9 + (duble elements in whatever order, e.g. 1 1 1 4 4 6)

感谢您的建议

【问题讨论】:

  • 也许List&lt;int&gt; 对你想做的事情会更容易
  • 提示:对数组进行排序,然后执行两次循环,第一次扫描它输出每个不同的值(即,每当它发生变化时),第二个输出非不同的值(即,在变化之后)输出每个相同的值)。使用IEnumerableyield return 可以更轻松地编写代码。如果您必须完全“就地”完成,请考虑在每一端开始两个指针,左侧接受唯一值,右侧累积额外的非唯一值。
  • 请说明左侧部分是否必须进行排序(因为答案表明每个人都不清楚)

标签: c# arrays sorting


【解决方案1】:

我得到了一个可以正常工作的example

using System.IO;
using System;

class Program
{
    static void Main()
    {
        int[] array = {1, 1, 6, 5, 4, 3, 4, 6, 1, 7, 2, 1, 4, 9};
        allDistinct(array);
    }

    static int[] allDistinct(int[] array)
    {
        Array.Sort(array);
        printArray(array); // first step monitoring
        int n = array.Length;

        // iterate through array
        for(int i=0;i<n-1;i++)
        {
            // bubble push duplicates to the back
            while(array[i] == array[i+1])
            {
                for(int j=i+1;j<n-1;j++)
                {
                    array[j] = array[j+1];
                }
                array[n-1] = array[i];
                n--;
            }

            printArray(array); // loop steps monitoring
        }

        return array;
    }

    static void printArray(int[] array)
    {
        Console.WriteLine(string.Join(" ", array));
    }
}

这会产生以下输出:

1 1 1 1 2 3 4 4 4 5 6 6 7 9 
1 2 3 4 4 4 5 6 6 7 9 1 1 1 
1 2 3 4 4 4 5 6 6 7 9 1 1 1 
1 2 3 4 4 4 5 6 6 7 9 1 1 1 
1 2 3 4 5 6 6 7 9 4 4 1 1 1 
1 2 3 4 5 6 6 7 9 4 4 1 1 1 
1 2 3 4 5 6 7 9 6 4 4 1 1 1 
1 2 3 4 5 6 7 9 6 4 4 1 1 1

请注意,这将更改原始数组的顺序返回它,因为数组不能按值传递 在 C# 中。


编辑:

关于气泡推送,您可以改为计算重复的数量并加大力度:

static int[] allDistinct2(int[] array)
{
    Array.Sort(array);
    printArray(array);
    int n = array.Length;

    for(int i=0;i<n;i++)
    {
        int countDup = 0;
        int iValue = array[i];

        // Count the number of duplicates
        for(int j=i+1;j<n && array[j] == iValue;j++)
        {
            countDup++;
        }

        Console.WriteLine("// " + countDup + " time(s) the value " + iValue);
        if(countDup > 0)
        {
            for(int j=i+1;j<n-countDup;j++)
            {
                array[j] = array[j+countDup];
            }
            for(int j=n-countDup;j<n;j++)
            {
                array[j] = iValue;
            }
        }
        n-=countDup;

        printArray(array);
    }

    return array;
}

这会产生:

1 1 1 1 2 3 4 4 4 5 6 6 7 9
// 3 time(s) the value 1
1 2 3 4 4 4 5 6 6 7 9 1 1 1
// 0 time(s) the value 2
1 2 3 4 4 4 5 6 6 7 9 1 1 1
// 0 time(s) the value 3
1 2 3 4 4 4 5 6 6 7 9 1 1 1
// 2 time(s) the value 4
1 2 3 4 5 6 6 7 9 4 4 1 1 1
// 0 time(s) the value 5
1 2 3 4 5 6 6 7 9 4 4 1 1 1
// 1 time(s) the value 6
1 2 3 4 5 6 7 9 6 4 4 1 1 1
// 0 time(s) the value 7
1 2 3 4 5 6 7 9 6 4 4 1 1 1
// 0 time(s) the value 9
1 2 3 4 5 6 7 9 6 4 4 1 1 1

Updated coding-ground link

【讨论】:

  • "请注意,这将改变原始数组的顺序并返回它,因为在 C# 中数组不能按值传递。" 没有什么可以阻止您创建和作用于函数中数组的不同副本。
  • @Pac0 没有例外要求 - 必须创建额外的数组
  • @Rafalon 是正确的,谢谢!但是时间复杂度呢?我们从排序得到 O(nlogn) + O(n*n) 对吧?
  • @mike.dl 听起来是正确的(好吧,我不是时间复杂度方面的专家,但看起来冒泡排序是 O(n²) 所以也许使用 O(nlogn) 算法会给你什么你想要)
【解决方案2】:

将数组的所有不同元素放在同一数组的左侧

我没有看到对结果集进行排序的任何要求。唯一的要求是对元素进行排列,以使所有重复项都晚于所有不同的值。

如果不需要对结果集进行排序,则没有理由调用Array.Sort()(这确实是一种作弊);我们可以编写自己的解决方案,自己整理数字。

此算法通过从末尾开始并查找重复项来翻转问题。当找到一个时,它被交换到位,并且数组的上边界向下移动。如果最后的元素没有重复,我们将它与第一个元素交换,并向上调整下边界,这样我们就不会再看它了。

public class Program
{
    public static int[] DistinctFirst(int[] arr)
    {
        var lbound = 0;
        var ubound = arr.GetUpperBound(0);
        var i = ubound;
        while ( i>lbound )
        {
            var k = i;
            for (int j=i-1; j>=lbound; j--)
            {
                if (arr[j] == arr[i])
                {
                    Swap(ref arr[j], ref arr[i-1]);
                    i--;
                }
            }
            if (k == i)
            {
                Swap(ref arr[i], ref arr[lbound]);
                lbound++;
            }
            else
            {
                i--;
            }
        }
        return arr;
    }

    public static void Swap(ref int a, ref int b)
    {
        int c = a;
        a = b;
        b = c;
    }

    public static void Main() 
    {
        int[] arr = {1, 1, 6, 5, 4, 3, 4, 6, 1, 7, 2, 1, 4, 9};
        int[] result = DistinctFirst(arr);

        foreach (var i in result)
        {
            Console.WriteLine(i);
        }
    }
}

输出:

9
7
2
3
5
4
4
4
6
6
1
1
1
1

Code on DotNetFiddle

【讨论】:

  • 第一个 6 出现在您的输出中的三个 4 之后是怎么回事? (1s 也一样)
  • 再一次,我没有看到任何排序要求。排列数组,使重复的​​数字排在最后。它们可能以任何顺序出现。
  • "我的输出应该是1 2 3 4 5 6 7 9 +(以任何顺序的双元素,例如1 1 1 4 4 6" - 仍然是 1、4 和 6 应该 i> 在左侧出现一次 - 并且 我觉得如果 双元素 [可以] 以任何顺序 这意味着左侧部分应该是原样(即排序)
  • @HenkHolterman 我知道所有选项,为了代码清晰,我选择了那个。您肯定不会告诉我检索长度然后减去一个更有效吗?
【解决方案3】:

您可以使用 O(N) 额外空间和 O(nlogn) 时间轻松解决此问题。 这是我的 python 解决方案:我的解决方案背后的想法是首先对 arr 进行排序,同时在 map 或 dict 中保留不同的元素,现在你只需要应用一个逻辑,你可以在 gfg 中轻松找到将所有零向一侧移动,就像我们必须这样做将不同的元素移到一侧:

arr = [1 ,1, 6, 5 ,4, 3, 4, 6, 1, 7, 2, 1, 4, 9]``
mp={}

for i in range(len(arr)):
    if arr[i] not in mp:
        mp[arr[i]]=1

 arr.sort()

 j = 0
 for i in range(len(arr)):
     if arr[i] in mp and mp[arr[i]]!=0:
          mp[arr[i]]-=1
          arr[i],arr[j]=arr[j],arr[i]
          j+=1
  print(arr)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-20
    • 2021-12-06
    • 1970-01-01
    相关资源
    最近更新 更多