从数组中删除重复的数字,并在c++中将它们添加到末尾

Removing Duplicate Numbers from an Array and Adding them to the end at c++

本文关键字:添加 c++ 删除 数组 数字 并在      更新时间:2023-10-16

我在data.txt文件中有一个数组,如9 3 9 4 5 4 3 7 1 9 6

我需要找到重复的数字并将它们从数组中删除。

之后,我需要在数组的末尾收集它们。

我写了一个代码,输出是9 3 4 5 7 1 6 9 3 4 9,但我需要把重复的数字放在数组中,按照它们在原始数组中出现的顺序。

所以我需要得到{ 9, 3, 4, 5, 7, 1, 6, 9, 4, 3, 9 }作为输出。

我可以用代码做些什么来达到我的目标

#include <iostream>
#include <fstream>
using namespace std;
#define SZ 11
int main(){
    ifstream fs("data.txt");
    if (!fs)
        return 0;
    int a[SZ];
    for (int i = 0; i < SZ; ++i)
        fs >> a[i];
    for (int k=0; k<SZ; k++) {
        for (int j=k+1; j< SZ ; j++) {
            if (a[j]==a[k]) {
                for (int l=j; l<SZ-1; l++) {
                    a[l]=a[l+1];
                }
                a[10]=a[k];
            }
        }
    }
    for (int i = 0; i < SZ; ++i)
        cout << a[i];
    return 1;}

这里有一个策略。

保留一个条目在并行数组中是否重复的概念。

先打印不重复的数字。

然后打印重复的数字。

#include <iostream>
#include <fstream>
using namespace std;
#define SZ 11
int main()
{
   ifstream fs("data.txt");
   if (!fs)
      return 0;
   int a[SZ];
   int isDuplicate[SZ];
   for (int i = 0; i < SZ; ++i)
   {
      fs >> a[i];
      isDuplicate[i] = false;
   }
   for (int k=0; k<SZ; k++) {
      for (int j=k+1; j< SZ ; j++) {
         if (a[j]==a[k])
         {
            isDuplicate[j] = true;
         }
      }
   }
   // Print the non-duplicates
   for (int i = 0; i < SZ; ++i)
   {
      if ( !isDuplicate[i] )
         cout << a[i] << " ";
   }
   // Print the duplicates
   for (int i = 0; i < SZ; ++i)
   {
      if ( isDuplicate[i] )
         cout << a[i] << " ";
   }
   cout << endl;
   // Not sure why you have 1 as the return value.
   // It should be 0 for successful completion.
   return 0;
}

如果你想保持顺序,你必须将每个数字与前一个数字进行比较,而不是与下一个数字比较。您的程序变成:

#include <iostream>
#include <iostream>
#include <fstream>
using namespace std;
#define SZ 11
int main(){
ifstream fs("data.txt");
    if (!fs)
        return 0;
    int a[SZ];
    for (int i = 0; i < SZ; ++i)
        fs >> a[i];
    // kk limits the number of iteration, k points to the number to test
    for (int k=0, kk=0; kk<SZ; kk++, k++) {
        for (int j=0; j< k ; j++) {
            if (a[j]==a[k]) {
                for (int l=k; l<SZ-1; l++) {
                    a[l]=a[l+1];
                }
                a[SZ - 1]=a[j];
                // a[k] is a new number and must be controlled at next iteration
                k -= 1;
                break;
            }
        }
    }
    for (int i = 0; i < SZ; ++i)
        cout << a[i];
    return 1;}

我倾向于尝试一种使用std::remove_if并具有重复数据消除一元谓词的解决方案。这应该会保留重复元素的顺序。

OP(@kuvvetkolu)的原始示例具有O(SZ^3)复杂性,这是残酷的@RSahu的解是O(SZ^2),这是一个改进(也是正确的),但这不需要O(N^2)。。。

这是一个只会产生空间开销的版本(假设O(1)哈希表查找)。您可以使用unordered_set(哈希表)来跟踪您是否已经看到特定的数字,将其放入适当的向量中,然后在末尾合并向量。

#include <iostream>
#include <fstream>
#include <unordered_set>
#include <vector>
int main() {
    std::ifstream fs("data.txt");
    if (!fs)
        throw std::runtime_error("File not found!");
    std::vector<int> a;
    std::vector<int> dups;
    std::unordered_set<int> seen;
    int d;
    while (fs) {
        fs >> d;
        if (seen.find(d) == seen.end())
        {
            a.push_back(d);
            seen.insert(d);
        }
        else
        {
            dups.push_back(d);
        }
    }
    a.insert(a.end(), dups.begin(), dups.end());
    for (auto n : a)
        std::cout << n << " ";
    return 0;
}