C-从阵列中删除重复项

问题描述

我对编程还很陌生,我写了一段代码从逻辑上删除重复项,从逻辑上讲,它应该可以工作,但是没有...。我对它进行了多次逻辑测试,这很有意义...

这是代码

#include <stdio.h>

int rmDuplicates(int arr[],int n)
{
    int i,j;
    for (i = 0; i < n; i++) {
        if (arr[i] == arr[i + 1]) {
            for (j = i + 1; j < n - 1; j++) {
                arr[j] = arr[j + 1];
            }
            n--;
        }
        return n;
    }
}

int main()
{
    int n,i;
    scanf("%d",&n);
    int arr[n];
    for (i = 0; i < n; i++) {
        scanf("%d",&arr[i]);
    }

    n = rmDuplicates(arr,n);
    for (i = 0; i < n; i++) {
        printf("%d",arr[i]);
    }
    printf("\n%d",n);
    return 0;
}

解决方法

您的“ return n”在错误的位置,并且在第一个循环之后返回。

for(i=0;i<n;i++) {
    if(arr[i] == arr[i+1]) {
        for(j=i+1;j<n-1;j++) {
            arr[j] = arr[j+1];                              
        }
        n--;
    }
    return n; // <---- this
}
// <-- should be here.

作为确认,如果我将return n;移到循环外,代码将起作用。但是,它只会删除连续重复项,因为您只能对照连续的arr [i + 1]检查arr [i]。

(此外,循环应该在n-1处停止,因为否则arr [n-1 + 1]是数组之外的arr [n]。

最后一个问题是,如果您有

                   n
 ...5,...,5,6
    i      j

,然后将第一个5与第二个进行比较,找到一个重复的副本,然后将所有后续内容移动一步,在第j个位置您将再次拥有5,但是j现在将递增,您将将第一个5与第6个进行对比,而不是第三个5,则未找到重复项:

                n
 ...5,6
    i         j

由于这个原因,当找到匹配项时,您需要将j倒回一并重复该测试:

int rmDuplicates(int arr[],int n) {
    int i,j,k;
    for (i=0;i<n-1;i++) {
        for (j=i+1; j < n; j++) {
                if(arr[i] == arr[j]) {
                    n--;
                    for (k=j;k<n;k++) {
                        arr[k] = arr[k+1];
                    }
                    j--;
                }
        }
    }
    return n;
}

从性能的角度来看,上述算法为O(n ^ 2),也就是说,如果数组列表增加一倍,则该算法所花费的时间是原来的四倍。如果加倍,则需要9倍的时间。

因此,更好的算法是首先对数组进行原位排序,以使1 3 2 7 2 3 5变成1 2 2 3 3 5 7(这花费了O(n log n),并且增长得更慢);那么您只需“压缩”跳过重复项的数组,即O(n)并得到1 2 3 5 7

int i,j;
for (i = 0,j = 1; j < n;) {
    if (arr[i] == arr[j]) {
        j++;
        continue;
    }
    i++;
    if (j != (i+1)) {
        arr[i] = arr[j];
    }
    j++;
}
n = i+1;
,
size_t removeDups(int *arr,size_t size)
{
    if(arr && size > 1)
    {
        for(size_t current = 0; current < size - 1; current++)
        {
            size_t original_size = size;
            size_t copypos = current + 1;
            for(size_t cpos = current + 1; cpos < original_size; cpos++)
            {
                if(arr[current] == arr[cpos])
                {
                    if(cpos < original_size -1)
                    {
                        if(arr[current] != arr[cpos + 1])
                        {
                            arr[copypos++] = arr[cpos + 1];
                            cpos++;
                        }
                    }
                    size--;
                }
                else
                {
                    arr[copypos++] = arr[cpos];
                }
           }
        }
    }
    return size;
}

int main(void)
{
    int arr[] = {1,1,2,3,4,6,7,8,2};
    size_t size = sizeof(arr) / sizeof(arr[0]);

    size = removeDups(arr,size);
    for(size_t index = 0; index < size; index++)
    {
        printf("%d\n",arr[index]);
    }
}