1

这是我几天来一直试图解决的问题。

我需要编写一个获取排序数组的程序。程序会将 999 放在两个相邻块具有相同值的位置,然后将所有 999 放在数组的末尾。我需要在不使用另一个数组的情况下执行此操作,并且程序必须是 O(n)。

示例输入:

50,60,60,72,81,81,81,81,93,93

所需的输出:

50,60,72,81,93,999,999,999,999,999

另一个例子:

1,1,2,3,4,4,5,6,6

所需的输出:

1,2,3,4,5,6,999,999,999

我的代码。它不工作。对于第一个示例,输出没问题。对于第二个示例,我得到 1,2,3,4,5,4,5,6,-14568127(超出数组范围)

我的算法是我用两个索引 i 和 j 遍历数组,如果 a[i]!=a[i+1] 然后我推进 i。如果它们相等,则 j 查找下一个唯一值,并将其放入 a[i+1]。

我很想听听更好的想法或代码来做到这一点。在 C.

while((j!=size-1)&&(a[size-1]!=a[i]))
{
     if(a[i]!=a[i+1])
     {
         i++;
         j=i;
     }
     if(a[i]==a[i+1])
     {
         j=i;
         while(a[i]==a[j])
               j++;
         a[i+1]=a[j];
         i++;
         if(j!=size-1)
              j=i;
     }
}
i++
for(;i<size;i++)
      a[i]=999;

我已经编辑了代码,现在我按照陈的建议进行了。首先,我遍历数组,将 999 放在双打所在的位置,但当我想切换时出现问题。这是我为重新排序数组而编写的代码:每次我将 999 放在某个地方时,count++。

它适用于我完美给出的两个示例。谢谢大家。

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
void main()
{
    int *a;
    int i=0,j=0,size,count=0;
    printf("Enter the size of the array\n");
    scanf("%d", &size);
    a=(int *)calloc(size,sizeof(int));
    printf("Enter %d numbers\n",size);
    for(i=0;i<size;i++)
        scanf("%d",&a[i]);
    printf("The array recieved is :\n");
    for(i=0;i<size;i++)
        printf(" %d ", a[i]);
    i=0;
    printf("\n");
    for(i=0;i<size;i++)
    {
        if(a[i]==a[i+1])
        {
            j=i+1;
            while(a[i]==a[j])
            {
                a[j]=999;
                j++;
            }
            count++;
        }
    }
    while(count!=0)
    {
        for(i=0;i<size-1;i++)
        {
            j=i;
            if(a[j]==999)
            {
                a[j]=a[j+1];
                a[j+1]=999;
            }
        }
        count--;
    }
    printf("The new array is: \n");
    for(i=0;i<size;i++)
        printf(" %d ",a[i]);
    free(a);
    getch();
}
4

3 回答 3

0

假设这是针对学校练习,并且您不是为 Google 工作并且需要删除世界地图中位置的重复项,那么您的算法听起来是正确的。

对于非常多的潜在重复项,并且假设列表已排序,您可以使用基于搜索最近的较大元素的方法,然后通过测量两个元素之间的距离,您可能会发现更有效。

于 2012-12-20T23:02:20.233 回答
0

这是在O(n)中运行的一般方法:

假设:输入数组不包含999(如果包含也没关系,您只需要使用不同的标记值):

  • 遍历数组一次:
    • 对于每个元素,向前看下一个
    • 如果它与当前元素重复,请将其更改为999
    • 继续向前看并标记重复项,999直到您遇到不同的元素。
  • 你想要所有的999's 在最后,所以现在,保留 2 个单独的指针:
    • X用于跟踪第一个999在数组中的位置的索引
    • num跟踪我们在交换过程中所处位置的另一个索引
  • 再次遍历数组,999使用这两个指针交换所有有效数字。

这可能听起来令人困惑,所以这是一个使用您的示例之一的伪动画:(使用W作为哨兵代替“999”以提高可读性)

1,1,2,3,4,4,5,6,6,
1,W,2,3,4,4,5,6,6,
1,W,2,3,4,W,5,6,6,
1,W,2,3,4,W,5,6,W,
1,2,W,3,4,W,5,6,W,
1,2,3,W,4,W,5,6,W,
1,2,3,4,W,W,5,6,W,
1,2,3,4,5,W,W,6,W,
1,2,3,4,5,6,W,W,W,

再一次,但这次W用数字后缀标记,这样你就可以看到发生了哪些交换:

1,1,2,3,4,4,5,6,6,
1,W1,2,3,4,4,5,6,6,
1,W1,2,3,4,W2,5,6,6,
1,W1,2,3,4,W2,5,6,W3,
1,2,W1,3,4,W2,5,6,W3,
1,2,3,W1,4,W2,5,6,W3,
1,2,3,4,W1,W2,5,6,W3,
1,2,3,4,5,W2,W1,6,W3,
1,2,3,4,5,6,W1,W2,W3,
于 2012-12-20T23:09:10.653 回答
0

最简单的方法是先删除重复项,然后用999.

删除重复项是 O(n),填充数组是 O(n)。

于 2012-12-21T03:03:06.300 回答