我有一个整数数组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;
}
答案 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;
}