将20个数字输入到一个没有重复的数组中

Entering 20 numbers into an array with no duplicates

本文关键字:数组 一个 数字输入 20个      更新时间:2023-10-16
int main()
{
    int theArray [20] = {0};
    int userInput = 0;
    int populateCount = 0;
    cout << "Enter 20 integers between 10 and 100 inclusive. " << endl;
    while (populateCount < 20)
    {
        cin >> userInput;
        theArray[populateCount] = {userInput};
        if (userInput<10||userInput>100)
        {
            cout << "That is not a legal input. " << endl;
            populateCount - 2;
        }
        else
        {
            populateCount++;
        }
    }
    cout << "n";
    for (int i = 0; i < 20; i++)
    {
        cout << theArray[i] << endl;
    }
}

我已经完成了代码的基线。用户输入20个数字,它们被添加到数组中。如果小于10或大于100这不是合法的输入,我从计数中减去,他们可以继续。然后在用户完成数字输入后,它打印数组。然而,我一直在尝试不同的if语句在数组中消除重复,如(如果theArray[I] == theArray[I +1]然后[I +1] = 0)我想,如果我合并一个排序得到所有的0在结束工作,但是有一个更有效的方法来做到这一点?

在我回答之前,我建议我们稍微整理一下,使问题更清楚,并消除其他混淆。

误解

语句populateCount - 2没有效果。相反,你只是没有增加populateCount,这就是为什么循环不会前进。

我建议在循环中使用这种格式。它将"快乐"路径放在前面,这也将为处理第二部分提供一些更清晰的方法。

if (userInput >= 10 && userInput <= 100 ) {
    theArray[populateCount++] = userInput;
} 
else {
    std::cout << userInput << " is not legal input, must enter value "
              << "between 10 and 100. " << std::endl;
}  

序言

在我们解决这个问题之前,让我们先重构一下,这样我们就可以把它分解成一个函数,这样我们在工作的时候就不会打扰到其他的东西,也可以获得测试的灵活性,并简化可读性。

重构
/* this code is responsible for doing what is needed to 
 * only insert unique items */
bool insert( const int& input, int* array, int num_elements ) {
    // the fun part!
    // more to follow shortly
};
/* gets user input forcing input to be between min and max */
int getUserInput(int min, int max) {
    bool found = false;
    int result = 0; 
    /* this can be done with less code but this makes it easy
     * to see whats going on */
    while ( !found ) {
        cout << "Please enter a value between " << min << " and " << max << "." << endl;
        cin >> result;
        if ( result >= min && result <= max ) {
            found = true; //yes we could break or return from here
        } else {
            cout << result << " invalid. "<< endl;
        }
    }
    return result;
};
void printArray( const int* array, const int& size ) {
    for (int i = 0; i < size; i++)
    {
        cout << array[i] << endl;
    }
};
int main()
{
    const int totalElements = 20;
    int theArray [totalElements] = {0};
    int userInput = 0;
    int populateCount = 0;
    int minVal = 10;
    int maxVal = 100;
    cout << "Enter " << totalElements << " integers between " 
         << minVal << " and " << maxVal << " inclusive. " << endl;
    while ( populateCount < numElements )
    {
        //this will percievably loop until it's good
        userInput = getUserInput(minVal, maxVal);
        if ( insert( userInput, theArray, populateCount ) )
            ++populateCount; //increments if we did insert it
        }
    }
    cout << endl;
    printArray( theArray, totalElements );
}

解决问题

现在我们的问题很简单,我们只需要写出insert函数。这里有几个选择,你可以依次检查每个元素就像你说的那样,可能很慢,O(n)或者我们可以对数组进行排序,让它更快,O(log n) +排序成本。我认为其他不可用的可能性是使用std::set而不是数组,或者使用STL进行排序和查找工作。请注意,在这些模式下,如果数字已经存在,insert实际上不会进行插入。

另一个独特的想法是使用大小为max-min的数组,并在找到input-min时简单地将索引标记为true。这将以大小为代价,这取决于最小和最大之间的差距。(这实际上是一个哈希函数)

我们从重构中得到的好处是,你可以依次编写和尝试这些解决方案,甚至给它们提供相同的罐装输入,现在我们已经重构了,这样你就可以尝试并计算每个解决方案的时间。对于计时,我强烈建议您添加大量数字,并考虑大大扩展最小值和最大值,以了解每个选择的可伸缩性

相关文章: