将20个数字输入到一个没有重复的数组中
Entering 20 numbers into an array with no duplicates
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。这将以大小为代价,这取决于最小和最大之间的差距。(这实际上是一个哈希函数)
我们从重构中得到的好处是,你可以依次编写和尝试这些解决方案,甚至给它们提供相同的罐装输入,现在我们已经重构了,这样你就可以尝试并计算每个解决方案的时间。对于计时,我强烈建议您添加大量数字,并考虑大大扩展最小值和最大值,以了解每个选择的可伸缩性