我正在做一些家庭作业,我卡在一节,我需要移动所有重复的排序数组到数组的末尾。我知道如何用1个额外的数组,但没有额外的数组,我不知道(有点混乱的指针)
我尝试了这个想法:(但它不起作用,不知道为什么)
int main()
{
int newArr[12] = {1,2,2,2,3,3,5,6,7,7,9,9 };
int n = 12;
int first = 0;
int last = n - 1;
int* D = arr + 1;
int j = 0;
for (int i = 0; i < n; i++)
{
j = i + 1;
while (j < n)
{
if (newArr[i] != *D)
{
D++;
}
if (newArr[i] == *D)
{
swap(&newArr[i], &newArr[last]);
j++;
last--;
}
j++;
}
}
for (int i = 0; i < n; i++)
{
printf("%d", newArr[i]);
}
}
工作的2阵列版本:
int moveDuplicatesV1(int* arr, int n)
{
int* seen_before = (int*)calloc(n * 2 + 1, sizeof(int));
assert(seen_before);
int val = 0, count = 0, flag = 1;
int j = 0;
for (int i = 0; i < n; i++)
{
val = arr[i];
if (seen_before[arr[i] + n] == 0)
{
seen_before[arr[i] + n]++;
count++;
continue;
}
else if (flag)
{
j = i + 1;
flag = 0;
}
while (j < n)
{
if (seen_before[arr[j] + n] == 0)
{
count++;
seen_before[arr[j] + n]++;
swap(&arr[i], &arr[j]);
j++;
if (j == n)
{
free(seen_before);
return count;
}
break;
}
/*break;*/
j++;
if (j == n)
{
free(seen_before);
return count;
}
}
}
}
2条答案
按热度按时间d8tt03nd1#
考虑您的阵列:
听起来你是想:
如果我们从索引0开始并与索引1进行比较,它们是不同的,因此我们继续比较索引1和索引2。
dupes_found
变量从0
递增到1
。我们保存arr[i]
,并将数组的其余部分向前移动1个位置,然后将arr[i]
中的内容复制到数组的最后一个位置。因为我们已经移动了数组,所以我们没有向前移动,现在我们再次比较索引1和2,它们仍然是相同的,所以我们重复,再次递增
dupes_found
。当数组的长度减去
dupes_found
时,工作就完成了。实现可能类似于:
wlp8pajw2#
@Chris为你画了一些漂亮的图片,我编写了匹配的实现。从位置1而不是0开始是一个小的重构。我的实现,如下所述,返回一个指针指向第一个重复的值。
输出为:
您可以选择移动
n - d - i - 2
元素,并在a [d](而不是a [n-1])插入新的重复元素。这将反向排序重复分区。如果您关心,请在返回之前反向排序重复分区。这可能会快一些。另一种优化是通过如上所述将第一个复制到
tmp
中来移动(r-1)个重复值的运行,用memmove()
创建(r-1)个孔,然后在该孔中写入tmp
的(r-1)个副本(在a[d-r-1]
或a[n-r-1]
处)。