如何找到对整数数组进行排序的最小步骤数

时间:2013-06-13 03:57:00

标签: c# algorithm

我有一个整数数组int[] number = { 3,4,2,5,1};

对它进行排序的最小步数应为2.但我得到的是4。

static void Main(string[] args)
        {
            int[] number = { 3,4,2,5,1};

           int result =  get_order(number);

            Console.ReadKey();
        }

        public static int get_order(int[] input1)
        {
            input1 = input1.OrderByDescending(o => o).ToArray();
            bool flag = true;
            int temp;
            int numLength = input1.Length;
            int passes = 0;

            for (int i = 1; (i <= (numLength - 1)) && flag; i++)
            {
                flag = false;
                for (int j = 0; j < (numLength - 1); j++)
                {
                    if (input1[j + 1] > input1[j])
                    {
                        temp = input1[j];
                        input1[j] = input1[j + 1];
                        input1[j + 1] = temp;
                        flag = true;
                    }
                }
                passes++;
            }
            return passes+1;
        }

问题是什么以及我需要在代码中做些什么更改?

修改

实施@Patashu,算法,

public static int get_order(int[] input1)
        {
            var sorterArray = input1.OrderByDescending(o => o).ToArray();
            var unsortedArray = input1;
            int temp1;
            int swap = 0;

            int arrayLength = sorterArray.Length;
            for (int i = 0; i < arrayLength; i++)
            {
                if (sorterArray[i] != unsortedArray[i])
                {
                    temp1 = unsortedArray[i];
                    unsortedArray[i] = sorterArray[i];
                    for (int j = i + 1; j < arrayLength; j++)
                    {
                        if (unsortedArray[j] == sorterArray[i])
                        {
                            unsortedArray[j] = temp1;
                            swap++;
                            break;
                        }
                    } 
                }
            }

            return swap;
        }

6 个答案:

答案 0 :(得分:2)

您的算法存在的问题是它只会尝试交换相邻的元素。

3,4,2,5,1最好通过交换3与5,这是一个不相邻的交换,然后2与3交换。

所以,我建议您通过执行以下操作找到更好的算法:

1)首先,使用C#的内置排序功能将数组按降序排序。

2)现在,您可以使用此排序数组作为比较 - 从左到右遍历数组。每当你看到未排序数组中的一个元素!=到排序数组中同一空间中的元素时,请查看排序数组所在值的未排序数组,并进行一次交换。

e.g。

3,4,2,5,1

使用Sort排序 - &gt; 5,4,3,2,1是我们的排序数组

3是!= 5 - 查看未排序的数组5 - 找到它,交换它们。

未分类现在是5,4,2,3,1

4 == 4

2是!= 3 - 查看未排序的数组3 - 找到它,交换它们。

未分类现在是5,4,3,2,1

2 == 2

1 == 1

我们处于未排序数组的末尾,我们进行了两次交换。

编辑:在您的算法实现中,它看起来几乎正确,除了

而不是

unsortedArray[j] = sorterArray[i];
unsortedArray[i] = temp1;

你有它倒退,你想要

unsortedArray[j] = temp1;
unsortedArray[i] = sorterArray[i];

答案 1 :(得分:2)

既然你问为什么要获得4个步骤,而不是如何计算传球,那么正确的方法是简单地逐步完成你的代码。在您的情况下,代码非常简单,可以在一张纸上,在调试器中或添加调试语句中单步执行。

Original: 3, 4, 2, 5, 1

Pass: 1: 4, 3, 5, 2, 1
Pass: 2: 4, 5, 3, 2, 1
Pass: 3: 5, 4, 3, 2, 1
Pass: 4: 5, 4, 3, 2, 1

基本上你看到的是每次迭代都会将一个数字排序到正确的位置。在传球结束时,一个2位于正确的位置。然后3,4,5。

啊!但这只是你说的3次传球。但是你实际上正在递增passes而不管flag,这表明你实际上做了一个额外的步骤,其中数组被排序(以相反的顺序),但你不知道这一点所以你必须经过并仔细检查(这是第4遍)。

答案 2 :(得分:1)

为了提高性能,你不需要从头开始检查数组。 比最后一个相等的元素好。

static int MinimumSwaps(int[] arr)
{
    int result = 0;
    int temp;
    int counter = 0;
    for (int i = 0; i < arr.Length; ++i)
    {
        if (arr[i] - 1 == i)
        {
            //once all sorted then
            if(counter==arr.Length)break;
            counter++;
            continue;
        }
        temp = arr[arr[i]-1];
        arr[arr[i] - 1] = arr[i];
        arr[i] = temp;
        result++;//swapped
        i = counter ;//needs to start from the last equal element
    }
    return result;
}

答案 3 :(得分:0)

一开始:

{ 3,4,2,5,1}; // passes = 0

第1轮结果:

{ 4,3,2,5,1};
{ 4,3,5,2,1}; // passes = 1

第2轮结果:

{ 4,5,3,2,1}; // passes = 2

第3轮重播:

{ 5,4,3,2,1}; // passes = 3 and flag is set to true

第4轮重播:

{ 5,4,3,2,1}; // same result and passes is incremented to be 4 

答案 4 :(得分:0)

你没有提到数组应该按降序排序,这通常不是默认的预期行为(至少在“C”/ C ++中)。转:

3, 4, 2, 5, 1

成:

1, 2, 3, 4, 5

确实需要4次(非相邻)互换。但是,把它变成:

5, 4, 3, 2, 1

只有两次掉头就够了。以下算法查找交换操作的O(m)中的交换次数,其中m是交换次数,其总是严格小于数组中的项目数n(可选地,复杂性是循环迭代的O(m + n)

int n = 5;
size_t P[] = {3, 4, 2, 5, 1};

for(int i = 0; i < n; ++ i)
    -- P[i];
// need zero-based indices (yours are 1-based)

for(int i = 0; i < n; ++ i)
    P[i] = 4 - P[i];
// reverse order?

size_t count = 0;
for(int i = 0; i < n; ++ i) {
    for(; P[i] != i; ++ count) // could be permuted multiple times
        std::swap(P[P[i]], P[i]); // look where the number at hand should be
}
// count number of permutations

这确实找到了两次互换。请注意,在此过程中会破坏排列。 可以找到此算法的测试用例here(使用Visual Studio 2008测试)。

答案 5 :(得分:0)

这是您问题的解决方案:)

static int MinimumSwaps(int[] arr)
    {
        int result = 0;
        int temp;
        int counter = 0;
        for (int i = 0; i < arr.Length; ++i)
        {
            if (arr[i] - 1 == i)
            {
                //once all sorted then
                if(counter==arr.Length)break;
                counter++;
                continue;
            }
            temp = arr[arr[i]-1];
            arr[arr[i] - 1] = arr[i];
            arr[i] = temp;
            result++;//swapped
            i = 0;//needs to start from the beginning after every swap
            counter = 0;//clearing the sorted array counter
        }
        return result;
    }