C# 将数组中所有不同的元素放在C中的左侧#

C# 将数组中所有不同的元素放在C中的左侧#,c#,arrays,sorting,C#,Arrays,Sorting,我试图编写一个程序,将数组中所有不同的元素放在同一数组的左边,并将所有其他(非不同的)元素按任意顺序放在后面。时间复杂度必须为O(n logn),即使用排序,并且不必创建额外的数组。我尝试使用以下代码打印不同的元素: using System; using System.Diagnostics; public class Program { public static void Main() { int []arr = {1, 1, 6, 5, 4, 3,

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

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]);
    }
}
然后使用辅助函数在Main()中打印数组

在哪里

我的输出应该是

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

我得到了一份充分发挥作用的:


请注意,这将更改原始数组的顺序,并返回它,因为在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;
}

我得到了一份充分发挥作用的:


请注意,这将更改原始数组的顺序,并返回它,因为在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;
}

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

我不认为需要对结果集进行排序。唯一的要求是对元素进行排列,以便所有重复项都晚于所有不同的值

如果结果集不需要排序,则没有理由调用
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

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

我不认为需要对结果集进行排序。唯一的要求是对元素进行排列,以便所有重复项都晚于所有不同的值

如果结果集不需要排序,则没有理由调用
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

也许一个
列表会更容易实现提示:对数组进行排序,然后执行两个循环,第一个扫描它输出每个不同的值(即每当它发生变化时),第二个输出非不同的值(即在变化后输出每个相同的值)。使用
IEnumerable
yield return
可以简化编码。如果你必须完全把它放在适当的位置,考虑在两端都有两个指针,左边接受唯一的值,右边累积额外的非唯一值。也许一个
列表
会更容易实现你想要做的提示:对数组排序,然后做两个循环,第一个扫描它,输出每个不同的值(即每当它改变),第二个输出非不同的值(即改变后输出每个相同的值)。使用
IEnumerable
yield return
可以简化编码。如果你必须完全把它放在适当的位置,考虑在两端都有两个指针,左边接受唯一的值,右边累积额外的非唯一值。在输出中,第一次出现的
6
是如何在三次
4
之后出现的?(与
1
s相同)同样,我看不到任何排序要求。数组的排列方式使重复的数字排在最后。它们可能以任何顺序出现。“我的输出应该是
12345679
+(以任何顺序的双元素,例如
141456
)”-仍然1、4和6应该在左侧出现一次-我觉得如果双元素[可以]以任何顺序,它意味着左侧部分应该保持原样(即排序)@HenkHolterman我知道所有的选项,为了代码清晰,我选择了那个选项。你肯定不会告诉我检索长度然后减去一更有效?你的输出中第一次出现的
6
怎么会在三次
4
之后出现?(与
1
s相同)同样,我看不到任何排序要求。数组的排列方式使重复的数字排在最后。它们可能以任何顺序出现。“我的输出应该是
12345679
+(以任何顺序的双元素,例如
141456
)”-仍然1、4和6应该在左侧出现一次-我觉得如果双元素[可以]以任何顺序,它意味着左侧部分应该保持原样(即排序)@HenkHolterman我知道所有的选项,为了代码清晰,我选择了那个选项。您肯定不会告诉我检索长度然后减去1更有效吗?“请注意,这将改变原始数组的顺序并返回它,因为数组不能通过C#中的值传递。”没有任何东西可以阻止您在函数中创建数组的不同副本并对其执行操作。@Pac0除要求外,没有任何东西可以阻止您创建和处理数组的其他副本-不必添加其他数组created@Rafalon没错,谢谢!霍维夫
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
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