在没有重复的数组中输入20个数字

时间:2014-03-18 14:28:24

标签: c++

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;
    }
}

我已经完成了代码的基线。用户输入二十个数字,然后将它们添加到数组中。如果它小于10或大于100,那么它不是合法输入,我从计数中减去它们,并且它们被允许再次进入。然后在用户完成插入数字后,它将打印出数组。但是,我一直在尝试在数组中使用不同的if语句来消除重复,例如(如果theArray [i] == theArray [i + 1]然后[i + 1] = 0)我认为如果我在最后加入了一个排序以获得所有0,但是有更有效的方法吗?

1 个答案:

答案 0 :(得分:1)

在我回答之前,我建议我们稍微清理一下,以使问题更加清晰,并消除其他困惑。

误解

语句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实际上不会在数字已存在的情况下进行插入。

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

我们从重构中获得的优势是,您可以反过来编写并尝试这些解决方案,甚至可以在我们重构的同时为它们提供相同的预设输入,以便您可以尝试和计算每个解决方案。对于时间安排,我会强烈建议你添加大量数字并考虑大大扩展最小值和最大值来理解每个选择的可扩展性