【问题标题】:C++: Removing a duplicate of the user input in an arrayC ++:删除数组中用户输入的副本
【发布时间】:2021-06-06 22:01:38
【问题描述】:

我从昨天开始就一直在尝试解决这个问题。程序应该接受来自用户的 N 个数字并将它们放在一个数组中。我已经做到了。但是,我似乎不知道如何“警告”用户输入重复并让用户再次输入。 这是我的代码:

# include <iostream>
using namespace std; 

int main () {
    
    int N, pos = -1, arr [N], i, j;
    int startLoop = 1;
    // the 'startLoop' variable is used so that the first user input can have the break function
    bool found = false;
    
    while (startLoop != 0) {
    
        cout << "Enter the number of integers to be entered: ";
        cin >> N;
        
            if (N <= 4) {
                cout << "Invalid. \n";
            }
            
            if (N > 4) {
                cout << "\n\nEnter " << N << " unique numbers: " ;
                for (i = 0; i < N; i++) {
                    cin >> arr [i];     
                    
                    for (j = 0; j < N && !found; j++) {
                        if (arr [j] == arr [i]) {
                            found = true;
                            cout << "Enter again: ";
                        }
                    }
            
            break;
            }
    }
}

【问题讨论】:

  • 首先,您使用的是非标准 C++ 的 VLA,并且您没有正确使用它。
  • 看起来你已经实现了一些东西 (found) 来检查是否有重复。不要说“代码不起作用”,而是解释代码到底出了什么问题(输入是什么,当前的输出是什么,有什么问题?)
  • 要检查数组中是否存在元素,您可以使用std::find function
  • 两个非常强大的高级规则(它们似乎从未在 CompSci 课程中教授过):1) 尽可能独立开发新功能,2) 解决一个更简单的问题。在这种情况下,尝试编写要求 N 个数字但拒绝接受“13”的代码。并编写一个函数来测试一个给定的数字 k 在数组的前 j 个元素中
  • int N, pos = -1, arr [N], i, j; 是非标准和UB,不是吗?

标签: c++ arrays duplicates user-input


【解决方案1】:

以下是您的代码的复制粘贴:

  1. 通过添加break,您将跳出外部for循环,您无法读取n个输入。

  2. 内部循环范围不正确,因为 i 是现在读取的值的总数。即如果 N= 10 并且在第三次迭代中,您尝试在 10 个元素之间循环以仔细检查最新数字是否重复,而您现在已经阅读了 3 个元素。

    if (N > 4) {
       cout << "\n\nEnter " << N << " unique numbers: " ;
       for (i = 0; i < N; i++) {
          cin >> arr [i];                    
          for (j = 0; j < N && !found; j++) {
            if (arr [j] == arr [i]) {
              found = true;
              cout << "Enter again: ";
            }
          }
          break;
       } 
    

    }

如何解决?

  • 一种方法是在单独的循环中读取输入,然后尝试查找重复项并将其删除。

  • 时间复杂度将为 O(n),因为您需要遍历列表两次,但是您需要在不移动所有元素的情况下有效地从数组中删除元素

  • 第二种方法就像您尝试实现的那样,但效率不高,因为每次用户添加新元素时,您都需要重新评估 i 数字(在最坏的情况下,当您填充数组末尾时 n 数字)。每次用户插入重复的数字时,都应重复此过程。

  • 最好的方法是将所有输入数字存储在一个哈希(集合)中,每次插入一个新数字时,检查它是否已经被用户建议。通过 unordered_set 搜索元素的时间复杂度将是 O(1)

【讨论】:

    【解决方案2】:

    问题:

    你的代码有很多问题:

    1. 您不应使用 VLA(可变长度数组),因为它们是非标准的。
    2. 在初始化之前使用 N 是 UB(未定义行为)。
    3. 您的方法效率不高,因为它平均检查 n/2 个元素 n 次,因此它的时间复杂度为 O(n^2)
    4. 您有许多未使用的变量和应该在更具体的范围内的变量。

    解决方案:

    1. 使用 std::vector insted 的 VLA。
    2. 在初始化 N 后调整向量的大小。
    3. 改变你的方法。
    4. 更改变量的范围。

    其他信息:

    1. using namespace std; 被认为是一种不好的做法(更多信息here)。
    2. 您可能应该向std::cin 添加输入检查以验证输入是否为数字。

    完整代码: 使用std::vector 在输入结束时检查重复一次(时间复杂度:O(n * log(n))。空间复杂度:O(n)):

    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    bool hasDuplicates(std::vector<int> toCheck)
    {
        std::sort(toCheck.begin(),toCheck.end());
        for(unsigned int i = 1; i < toCheck.size(); i++)
            if(toCheck[i] == toCheck[i-1])
                return true;
        return false;
    }
    
    int main () {
        std::vector<int> arr;
        int N;
    
        while (true) {
            std::cout << "Enter the number of integers to be entered: ";
            std::cin >> N;
            if (N <= 4) {
                std::cout << "Invalid: The number of integers to be entered must be bigger than 4. \n";
            }
            else {
                arr.resize(N);
                std::cout << "\n\nEnter " << N << " unique numbers: " ;
                for (int i = 0; i < N; i++)
                    std::cin >> arr [i];
                if(hasDuplicates(arr))
                    std::cout << "Invalid: The numbers must be unique. \n";
                else
                    break;
            }
        }
    }
    

    每次使用std::unordered_map 输入数字时检查重复项(时间复杂度:Amortized O(n)。空间复杂度:O(n)):

    #include <iostream>
    #include <vector>
    #include <unordered_set>
    
    int main () {
        std::vector<int> arr;
        std::unordered_set<int> alreadyAppeared;
        int N;
        std::cout << "Enter the number of integers to be entered: ";
        std::cin >> N;
        while (N <= 4) {
            std::cout << "Invalid: The number of integers to be entered must be bigger than 4. \n";
            std::cout << "Enter the number of integers to be entered: ";
            std::cin >> N;
        }
        arr.resize(N);
        std::cout << "\n\nEnter " << N << " unique numbers: \n";
        for (int i = 0; i < N; i++)
        {
            int entering;
            std::cout << "Enter unique number: ";
            std::cin >> entering;
            if(alreadyAppeared.find(entering) == alreadyAppeared.end())
            {
                alreadyAppeared.insert(entering);
                arr[i] = entering;
            }
            else
            {
                std::cout << "Invalid: The numbers must be unique. \n";
                i--;
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-06
      • 2021-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多