【发布时间】:2015-01-01 09:26:02
【问题描述】:
我写了一个程序,它接受 N 个代表学生技能水平的整数测试用例,并尝试找到可能的最小组的总数,如果唯一的限制是技能水平不能相等团队并且没有大于1的技能差距。所以下面的测试用例:
4 5 2 3 -4 -3 -5
会输出:
3
因为可能的团队是 {-4,-3,-5} 和 {4,5,2,3},因为第一组只有三个成员,所以输出是 3。
我决定使用链表和递归函数来解决这个问题。一个递归函数会在一个整数的左右寻找一个比它大一个大小的整数,如果找到一个,然后从列表中删除该元素并返回 1。另一个函数寻找一个小于 1 的整数也是如此。这应该导致一个组的总和,我可以比较不同的总和以找到最小的总和。不幸的是,当我尝试实现这一点时,不仅会遇到分段错误,而且经过几次迭代后出现的数字甚至都不是列表的一部分,而且非常大。
#include <cmath>
#include <cstdio>
#include <list>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int findHigherSkillLevel(int skillLevel, list<int>::iterator *it, list<int> &list) {
if (it == NULL) return 0;
if (**it == (skillLevel + 1)) {
//cout << "test3" << endl;
skillLevel++;
list.erase(*it);
*it = list.begin();
//cout << "Iterator in the higher skill level function if it finds a skill level higher by 1: " << **it << endl;
//cout << "The skill level is: " << skillLevel << endl;
return 1 + findHigherSkillLevel(skillLevel, it, list);
} else {
//cout << "Iterator in the higher skill level function if it doesn't find one: " << **it << endl;
return findHigherSkillLevel(skillLevel, ++it, list);
}
return 0;
}
int findLowerSkillLevel(int skillLevel, list<int>::iterator *it, list<int> &list) {
if (it == NULL) return 0;
if (**it == (skillLevel - 1)) {
skillLevel--;
list.erase(*it);
*it = list.begin();
return 1 + findLowerSkillLevel(skillLevel, ++it, list);
} else {
//cout << "test2" << endl;
return findLowerSkillLevel(skillLevel, ++it, list);
}
return 0;
}
int findGroupsSizes(list<int>::iterator *it, list<int> &list) {
if (it == NULL) return 0;
int groupSize = 1;
int skillLevel = **it;
*it = list.erase(*it);
//cout << "Iterator value in the first function: " << **it << endl;
groupSize += findHigherSkillLevel(skillLevel, it, list) + findLowerSkillLevel(skillLevel, it, list);
return groupSize;
}
如果我要使用上面提到的测试用例,它会遍历 4、5、2,然后弹出一些奇怪的数字,最后出现 seg 错误。如果您从这些递归的列表中弹出迭代函数,是否不可能在递归函数上使用迭代器?
main() 实际上接受了 t 个测试用例,后跟 t 行 N 个分隔的整数。我使用以下作为测试用例:
4
7 4 5 2 3 -4 -3 -5
1 -4
4 3 2 3 1
7 1 -2 -3 -4 2 0 -1
如果重要的话,这里是主要的:
int main() {
int t; // the number of test cases
cin >> t;
vector<list<int> > skillLevels(t, list<int>());
// input for each test case
for (int i = 0; i < t; i++) {
int n; // number of students for this test case
cin >> n;
// initialize the list for this test case
for (int j = 0; j < n; j++) {
int skillLevel;
cin >> skillLevel;
skillLevels[i].push_back(skillLevel);
}
}
// recursively scan lists for smallest teams
for (int i = 0; i < t; i++) {
int minGroupNumber = skillLevels[i].size();
list<int>::iterator iterator = skillLevels[i].begin();
int skillLevel = skillLevels[i].front();
while (!skillLevels[i].empty()) {
iterator = skillLevels[i].begin();
int currentGroupSize = findGroupsSizes(&iterator, skillLevels[i]);
cout << currentGroupSize << endl;
if (currentGroupSize < minGroupNumber)
minGroupNumber = currentGroupSize;
//cout << minGroupNumber << endl;
if (!skillLevels[i].empty()) skillLevels[i].pop_front();
}
cout << minGroupNumber << endl;
}
return 0;
}
【问题讨论】:
-
erase返回的迭代器可能超出末尾,如果您删除最后一个元素,但在取消引用之前没有检查。 -
顺便说一句,你的递归是没有意义的。都是尾递归,可以用一个简单的循环代替。
标签: c++ list recursion iterator segmentation-fault