我有以下任务:
给出一组N个正数。编写一个程序,找到集合的中间元素。
输入:第一行有很多例子,
第二行是集合的长度。下一行是用空格分隔的集合的数字。
有点像这样:
2(例子数)
5(长度)
12 4 22 31 32(套)
8(长度)
22 33 44 11 55 66 88 99(设置)
然后你必须对集合进行排序并打印中间元素。
输出:
22(第一集中期元素)
44(第二组中期元素)
约束:N&lt; 10 ^ 11且每个数量的集合应该<10。 10 ^ 20个
所以我选择直接使用字符串,因为数字很大。这是我的代码:
#include <iostream>
#include <vector>
#include <sstream>
#include <algorithm>
#include <cstring>
using namespace std;
bool comparer (const string s1, const string s2)
{
return atoi(s1.c_str()) < atoi(s2.c_str());
}
int main()
{
int numberOfExamples;
cin >> numberOfExamples;
for (int i = 0; i < numberOfExamples; i++)
{
long length;
string input;
cin >> length;
string buffer;
while(getline(cin, input))
{
vector<string> v;
istringstream is(input);
while (is >> buffer) v.push_back(buffer);
sort (v.begin(), v.end(), comparer);
string middle;
if (v.size() % 2 == 0)
{
middle = v[v.size()/2 -1];
}
else
{
middle = v[v.size()/2];
}
cout << middle;
}
}
return 0;
}
编译完成后,在第二行停止输入第一个例子的长度,我得到类型0xC00000005的错误。任何帮助将不胜感激。
答案 0 :(得分:1)
您尝试实施的算法是:
上面的粗体部分要么失败,要么根本不做。例如,您的代码:
cin >> length;
string buffer;
while(getline(cin, input))
将读取格式化的长度为整数,但当前行的其余部分(可能只是换行符)保留在输入流中。因此getline
消耗 ,而不是测试值行。更糟糕的是,这意味着for循环中的所有逻辑都将使用空输入行,这意味着向量中不会存储任何值。这意味着当你到达这里时:
if (v.size() % 2 == 0)
{
middle = v[v.size()/2 -1];
}
v.size()
为零,这意味着v.size() % 2
为零,这意味着您的“中间”现在设置为v[-1]
,这显然是超出范围的。
所以最大的问题是你在格式化输入之后没有正确地消耗剩余行数据,这是开始C ++程序员的一个常见问题。 See this question and related answers
第二个问题,while (getline(...))
是错误的。这将消耗所有数据,直到文件结束。你只想要一行数据;并非所有剩余的数据行。修复之前提到的格式化输入问题后,while
应该是if
。
<强>代码强>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <vector>
#include <string>
#include <limits>
#include <iterator>
int main()
{
unsigned int numberOfExamples;
if (!(std::cin >> numberOfExamples) || numberOfExamples == 0)
return EXIT_FAILURE;
while (numberOfExamples-- > 0)
{
unsigned int n_tests = 0;
if (std::cin >> n_tests)
{
if (n_tests == 0)
continue;
// consume remainder of test lines
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// read set of values
std::string line;
if (std::getline(std::cin, line))
{
std::istringstream iss(line);
std::vector<int> v {
std::istream_iterator<int>(iss),
std::istream_iterator<int>() };
if (v.size() > 0)
{
std::sort(v.begin(), v.end());
if (v.size() % 2 == 0)
std::cout << v[v.size()/2-1] << '\n';
else
std::cout << v[v.size()/2] << '\n';
}
}
}
else
{
std::cerr << "Failed to read number of test values\n";
}
}
}
<强>输入强>
2
5
12 4 22 31 32
8
22 33 44 11 55 66 88 99
<强>输出强>
22
44
答案 1 :(得分:0)
我能看到的代码最大的问题是在比较器中使用atoi
是行不通的。如果输入数据大于int
可以容纳的内容,则atoi
将无效,因为它会尝试将字符串转换为int
。
你可以做的是将字符串相互比较。您必须考虑到大小,否则100
会在5
之前出现,但实施起来并不难。以下内容应该有效。
bool comparer (const string& s1, const string& s2)
{
if (s1.size() != s2.size())
return s1.size() < s2.size();
return s1 < s2;
}
请注意,我将s1
和s2
更改为引用,因为按值传递会产生大量副本并导致性能下降。
答案 2 :(得分:0)
谢谢大家! 我修复了我的代码,现在它正常工作了。这是修复
#include <iostream>
#include <vector>
#include <sstream>
#include <algorithm>
#include <cstring>
using namespace std;
bool comparer (const string& s1, const string& s2)
{
if (s1.size() != s2.size())
return s1.size() < s2.size();
return s1 < s2;
}
int main()
{
int numberOfExamples;
cin >> numberOfExamples;
cin.ignore();
vector<string> outputs;
for (int i = 0; i < numberOfExamples; i++)
{
long long length;
string input;
cin >> length;
cin.ignore();
string buffer;
if(getline(cin, input))
{
vector<string> v;
istringstream is(input);
while (is >> buffer) v.push_back(buffer);
if (v.size() != length)
{
cout << "Incorrect length!";
return 1;
}
sort (v.begin(), v.end(), comparer);
string middle;
if (v.size() % 2 == 0)
{
middle = v[v.size()/2 -1];
}
else
{
middle = v[v.size()/2];
}
outputs.push_back(middle);
}
}
for (vector<string>::iterator it = outputs.begin(); it != outputs.end(); it++)
{
cout << *it << endl;
}
return 0;
}
我也在一个新的向量中推送答案,当for循环结束时显示所有这些。还有最后一个问题。我应该每次从用户那里使用cin.ignore()吗?