从数组C ++删除重复项

时间:2018-10-10 13:15:19

标签: c++ arrays duplicates

我正在尝试创建一个简单的程序,该程序调用2个函数。第一个函数采用部分填充的数组,循环遍历并删除所有重复值。当从数组中删除一个值时,剩余的数字将向后移动以填补空白,即当函数完成时,该数组的所有空值都将在末尾在一起。

第二个函数打印更新的数组。

我当前的代码如下。目前,当我运行代码时,控制台显示: 2 6 0 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460。它应该显示:1 2 5 6如果工作正常。

此外,我不确定如何向后移动数组的其余元素,以便将空值放在最后。

#include "pch.h"
#include <iostream>
using namespace std;
void deleteRepeats(int *arr, int arraySize, int& posUsed);
void printArray(int *arr, int arraySize);

int main()
{
int arr[10] = { 1, 2, 2, 5, 6, 1};
int posUsed = 6;
int arraySize = 10;


deleteRepeats(arr, arraySize, posUsed);
printArray(arr, arraySize);

return 0;
}

void deleteRepeats(int *arr, int arraySize, int& posUsed)
{
{
    for (int i = 0; i < arraySize; i++)
    {
        for (int j = i; j < arraySize; j++)
        {
            if (arr[i] == arr[j])
            {
                for (int k = j; k < arraySize; k++)
                {
                    arr[k] = arr[k + 1];

                }
                posUsed--;

            }
            else
                j++;
        }
    }
}
}

void printArray(int *arr, int arraySize)
{
for (int i = 0; i < arraySize; i++)
{
    cout << arr[i] << "  ";
}
}

5 个答案:

答案 0 :(得分:2)

我会让std容器做您想做的事。

  • 排序向量
  • 使用eraseunique删除重复项。

这是代码

#include <vector>
#include <iostream>
#include <algorithm>

void print(std::vector<int> arr){
    for (const auto i : arr){
        std::cout << i <<" ";
    }
    std::cout <<"\n";
}

int main() {
    std::vector<int> arr{1, 2, 2, 5, 6, 1};    
    print(arr);

    sort( arr.begin(), arr.end() );
    arr.erase( unique( arr.begin(), arr.end() ), arr.end() );

    print(arr);
}

Ps。使用int *arr, int arraySize不太像C ++。请始终尝试使用适当的容器(几乎总是std::vector)。

编辑: 我改变了答案,因为我发现了这种速度比较(实际上回答了整个问题)。 What's the most efficient way to erase duplicates and sort a vector?

答案 1 :(得分:2)

更容易想象算法具有独立的输入和输出数组。然后,使用伪代码:

for i = 0 to input_array_size-1
    Is input[i] equal to input[j] for any j between 0 and i-1?
    Yes - do nothing
    No - copy input[i] to output

要使用共享的输入和输出来实现此目的,您需要具有两个数组大小,input_array_sizeoutput_array_size。然后,伪代码变为

output_array_size = 0
for i = 0 to input_array_size-1
    Is array[i] equal to array[j] for any j between 0 and output_array_size-1?
    Yes - do nothing
    No:
        copy array[i] to array[output_array_size]
        Increase output_array_size

注意:它将输出写入到曾经输入的位置,因此对重复项的检查应查看输出的所有元素。例如,如果您的数组为1, 2, 1, 3, 5, 6, 3,那么对于最后一个3,累积的输出为1, 2, 3, 5, 6,并且代码应将所有这些与当前元素进行比较。


为简化调试(显示“不执行任何操作”),可以将当前元素设置为-1。这样,如果您在执行过程中打印数组(用于调试),则可以更清楚地删除哪些元素。

答案 2 :(得分:2)

鉴于您的分配约束(比惯用的C ++更多的类似于C的代码),您可以像这样重写您的函数以使其起作用:

void deleteRepeats(int *arr, int arraySize, int& posUsed)
{
    for (int i = 0; i < posUsed; ++i)
    {
        int duplicates = 0;
        int j = i + 1;
        // find the first duplicate, if exists
        for ( ; j < posUsed; ++j)
        {
            if ( arr[i] == arr[j] ) {
                ++duplicates;
                break;
            }
        }
        // overwrite the duplicated values moving the rest of the elements...
        for (int k = j + 1; k < posUsed; ++k)
        {
            if (arr[i] != arr[k])
            {
                arr[j] = arr[k];
                ++j;
            }
            // ...but skip other duplicates
            else
            {
                ++duplicates;    
            }
        }
        posUsed -= duplicates;
    }
    // clean up (could be limited to the duplicates only)
    for (int i = posUsed; i < arraySize; ++i)
        arr[i] = 0;
}

答案 3 :(得分:1)

您只能看到两项更改

1:您声明了posUsed=6变量时遍历了整个数组,这是因为只有6个元素,因此在循环中,您需要遍历高达posUsed的数组,如{{ 1}} i<posUsed j<posUsed

2:第二个更改是在j循环k<posUsed中,因为您不需要将任何索引的元素与相同索引的元素进行比较,而必须将其与该索引之后的元素进行比较。如果将它与相同元素进行比较,它将是相同的,程序将删除该相同元素,从而导致错误。

更多的事情是,我们不要遍历j=i+1索引,因为在此之后数组已经为空/零,或者无论您叫什么,都为null

,如果您只想在数组末尾显示非重复元素而不是零,只需在posUsed语句前的if(arr[i]==0) return;函数循环中添加printArray

cout

答案 4 :(得分:0)

使用两个指针
以及数组是否排序

    int removeDuplicates(vector<int>& nums) {
        if(nums.size() == 0) return 0;
        int i = 0;

        for(int j = 1; j < nums.size(); j++)
            if(nums[j] != nums[i])  nums[++i] = nums[j];

        // return new array length
        return i + 1;
    }
//input: [1, 1, 2, 1] (arr1)
//output: 2 (returned length)
// print unique element
for(int i = 0; i < output; i++) cout << arr1[i] << '\n';
// [1, 2]
time complexity: O(N/2) -> O(N)
space complexity: O(1)