之前那篇说另外一种写法的雏形出现在我的脑海中,现在终于都写完并且调试完成了。现在放上来,以免到时候又忘记了写过的东西。
现在又重构了一下那段代码,而且进行了比较多的调试都没问题了应该是比较稳定的这段程序。现在把重构后的代码把原代码覆盖,7月29日更新
今天面试的时候面试官有看过我这段代码说我这段代码当中含有会让系统宕机的可能,然后我回来之后灰常仔细的看终于都发现了那个可能了,那个erase那个函数那里如果firstElemIter==lastElemIter的时候,第一个if进去了然后后面那个if进去之后firstElemIter就会判断不等于lastElemIter这个时候进行循环减减的操作会导致在第一个元素--的操作然后就会宕机,然后我发现是必然的但是为什么之前的调试没办法调试出来呢?我在微软的vs平台上面调试的,然后拿一个比较小的数组进去测试没想到到了那个第一个元素的时候--操作不会进行然后那个isDeleted()函数也不会调用循环直接退出了好奇怪啊,但是代码明明跟到这里连个报错都没有然后那个lastElemIter还是指向第一个元素,后来我把这段代码改了从新调试发现也没问题,现在就把那个改了的代码放上来还有之前的有问题的代码保留吧因为后面就不知道我之前出问题没发现的地方了。8月12日更新。
#include<vector> #include<list> #include<iostream> using namespace std; typedef vector<int> intArray_t; class StrangeInt { public: StrangeInt(); StrangeInt(int value); StrangeInt(const StrangeInt &ref); bool isDeleted(); void setDeleted(bool deleted); int getValue(); int getRefCount(); void incRefCount(); void decRefCount(); bool operator < (const StrangeInt &ref); private: int refCount; bool deleted; int value; }; class StrangeIter { public: StrangeIter(list<StrangeInt>::iterator &iter, list<StrangeInt> *array, list<StrangeInt>::iterator &firstElemIter, list<StrangeInt>::iterator &lastElemIter); list<StrangeInt>::iterator incIter(); list<StrangeInt>::iterator decIter(); list<StrangeInt>::iterator firstElem(); list<StrangeInt>::iterator lastElem(); void erase(); void insert(int value); bool isFirstElem(); list<StrangeInt>::iterator getCurIter(); void incItsRefCount(); void decItsRefCount(); bool isEmpty(); private: list<StrangeInt>::iterator &iter; list<StrangeInt> *array; list<StrangeInt>::iterator lastDelPos; bool lastHadDel; bool isFirst; list<StrangeInt>::iterator &firstElemIter; list<StrangeInt>::iterator &lastElemIter; bool hadDelFirst; bool hadDelLast; }; StrangeInt::StrangeInt(){ } StrangeInt::StrangeInt(int value) : value(value), refCount(0), deleted(false){ } StrangeInt::StrangeInt(const StrangeInt& ref) : value(ref.value), refCount(ref.refCount), deleted(ref.deleted) { } bool StrangeInt::isDeleted() { return deleted; } void StrangeInt::setDeleted(bool deleted) { this->deleted = deleted; } int StrangeInt::getValue() { return value; } int StrangeInt::getRefCount() { return refCount; } void StrangeInt::incRefCount() { refCount++; } void StrangeInt::decRefCount() { refCount--; } bool StrangeInt::operator < (const StrangeInt &ref) { return value < ref.value; } StrangeIter::StrangeIter(list<StrangeInt>::iterator &iter, list<StrangeInt> *array, list<StrangeInt>::iterator &firstElemIter, list<StrangeInt>::iterator &lastElemIter) : iter(iter), array(array), lastHadDel(false), isFirst(false), firstElemIter(firstElemIter), lastElemIter(lastElemIter){ } list<StrangeInt>::iterator StrangeIter::incIter() { if (iter == lastElemIter) { iter = array->end(); } else { while ((++iter)->isDeleted()); } return iter; } list<StrangeInt>::iterator StrangeIter::decIter() { if (!isFirstElem()) { while ((--iter)->isDeleted()); } return iter; } list<StrangeInt>::iterator StrangeIter::firstElem() { return firstElemIter; } list<StrangeInt>::iterator StrangeIter::lastElem() { return lastElemIter; } bool StrangeIter::isFirstElem() { if (firstElem() == iter) return true; return false; } void StrangeIter::erase() { hadDelFirst = false; hadDelLast = false; if (lastElemIter == firstElemIter) { hadDelFirst = true; hadDelLast = true; firstElemIter = array->end(); lastElemIter = array->end(); } else if (iter == firstElemIter) { hadDelFirst = true; while ((++firstElemIter)->isDeleted()); } else if (iter == lastElemIter) { hadDelLast = true; while ((--lastElemIter)->isDeleted()); } /* if (iter == firstElemIter) { hadDelFirst = true; if (lastElemIter == firstElemIter) { firstElemIter = array->end(); } else { while ((++firstElemIter)->isDeleted()); } } else hadDelFirst = false; if (iter == lastElemIter) { hadDelLast = true; if (lastElemIter == firstElemIter) { lastElemIter = array->end(); } else { while ((--lastElemIter)->isDeleted()); } } else hadDelLast = false; */ if (iter->getRefCount() > 0) { iter->setDeleted(true); lastDelPos = iter; lastHadDel = false; if (hadDelLast) iter = array->end(); else while((++iter)->isDeleted()); } else { if (iter == array->begin()) { isFirst = true; array->erase(iter++); if (hadDelLast) iter = array->end(); else if (iter->isDeleted()) while((++iter)->isDeleted()); } else { array->erase(iter--); lastDelPos = iter; if (!iter->isDeleted()) { iter->incRefCount(); } if (hadDelLast) iter = array->end(); else while((++iter)->isDeleted()); } lastHadDel = true; } } void StrangeIter::insert(int value) { if (lastHadDel) { if (isFirst) { iter = array->begin(); array->insert(iter, value); } else { iter = lastDelPos; if (!iter->isDeleted()) { iter->decRefCount(); } array->insert(++iter, value); } iter--; } else { lastDelPos->setDeleted(false); iter = lastDelPos; } if (hadDelFirst) { firstElemIter = iter; } if (hadDelLast) { lastElemIter = iter; } incIter(); } list<StrangeInt>::iterator StrangeIter::getCurIter() { return iter; } void StrangeIter::incItsRefCount() { iter->incRefCount(); } void StrangeIter::decItsRefCount() { iter->decRefCount(); } bool StrangeIter::isEmpty() { return firstElem() == array->end(); } int sumOfArray(const vector<int> &array) { int sum = 0; int size = array.size(); for (int i = 0; i < size; i++) { sum += array.at(i); } return sum; } class MaxDivHelper{ public: MaxDivHelper(list<StrangeInt> &array, vector<intArray_t> &result, int groupSize, list<StrangeInt>::iterator &iter); bool maxDivFun(int preSize, vector<int> &preArray); void setGroupSize(int groupSize); void setStart(); private: list<StrangeInt> &array; vector<intArray_t> &result; int groupSize; list<StrangeInt>::iterator &iter; list<StrangeInt>::iterator firstElemIter; list<StrangeInt>::iterator lastElemIter; }; MaxDivHelper::MaxDivHelper(list<StrangeInt> &array, vector<intArray_t> &result, int groupSize, list<StrangeInt>::iterator &iter) : array(array), result(result), groupSize(groupSize), iter(iter) , firstElemIter(array.begin()), lastElemIter(array.end()){ lastElemIter--; } void MaxDivHelper::setGroupSize(int groupSize) { this->groupSize = groupSize; iter = array.begin(); } void MaxDivHelper::setStart() { iter = firstElemIter; } bool MaxDivHelper::maxDivFun(int preSize, vector<int> &preArray) { while (iter != array.end()) { if ((preSize + iter->getValue()) <= groupSize) { preArray.push_back(iter->getValue()); StrangeIter autoInsertIter(iter, &array, firstElemIter, lastElemIter); autoInsertIter.erase(); if ((preSize + preArray.back()) == groupSize) { if (autoInsertIter.isEmpty()) { result.push_back(preArray); return true; } else { list<StrangeInt>::iterator retIter = lastElemIter; while ((--lastElemIter)->isDeleted()); vector<int> grpArray(1, retIter->getValue()); bool hadDel = false; if (retIter->getRefCount() > 0) { retIter->setDeleted(true); } else { hadDel = true; array.erase(retIter++); } setStart(); if (this->maxDivFun(grpArray.at(0), grpArray)) { result.push_back(preArray); return true; } if (hadDel) { array.insert(retIter, grpArray.at(0)); lastElemIter = --retIter; } else { retIter->setDeleted(false); lastElemIter = retIter; } } } else { if (maxDivFun(preSize + preArray.back(), preArray)) return true; } autoInsertIter.insert(preArray.back()); preArray.pop_back(); } else break; } return false; } void maxDiv(const vector<int> &array, vector<intArray_t> &result) { if (array.empty()) return; list<StrangeInt> retList(array.begin(), array.end()); retList.sort(); int maxNum = retList.back().getValue(); vector<int> preArray(1, maxNum); if (retList.size() == 1) { result.push_back(preArray); return; } retList.pop_back(); int sum = sumOfArray(array); if (sum % maxNum == 0) { result.push_back(preArray); int n = 0; while (retList.back().getValue() == maxNum) { result.push_back(preArray); retList.pop_back(); if (retList.empty()) return; n++; } preArray.at(0) = retList.back().getValue(); retList.pop_back(); MaxDivHelper maxDivHelper(retList, result, maxNum, retList.begin()); if (maxDivHelper.maxDivFun(preArray.at(0), preArray)) { return; } retList.push_back(preArray.at(0)); for (; n != 0; n--) { retList.push_back(maxNum); } preArray.at(0) = maxNum; result.clear(); } MaxDivHelper maxDivHelper(retList, result, maxNum, retList.begin()); for (int m = sum/maxNum; m > 0; m--) { if (sum % m == 0 ) { maxDivHelper.setGroupSize(sum / m); if (maxDivHelper.maxDivFun(preArray.at(0), preArray)) break; } } }
我的测试代码还是和以前一样很简单,现在暂时想不到什么比较好的测试代码。
int main() { int a[10000]; //int a[] = { 1, 2, 4, 5, 100 }; //int a[] = { 1, 1, 1, 1, 1, 1 }; //int a[] = { 3, 3, 4, 6, 2 }; //rand(); for (int i = 0; i < (sizeof(a) / sizeof(int)); i++) { // a[i] = i + 1; if (i % 2 != 0) a[i] = 1000 - a[i - 1]; else while ((a[i] = (rand() % 1000)) <= 0); } vector<int> array(a, a + (sizeof(a)/sizeof(int))); vector<intArray_t> result; maxDiv(array, result); cout << "{"; int resultSize = result.size(); for (int i = 0; i < resultSize; i++) { if (i != 0) cout << ", "; cout << "{"; vector<int> group = result.at(i); int groupSize = group.size(); for (int j = 0; j < groupSize; j++) { if (j != 0) cout << ", "; cout << group.at(j); } cout << "}"; } cout << "}"; cout << "\n"; cout << "The max group num that can divide to have same sum group is: " << resultSize; return 0; }
好像跑完上面这段代码花了几毫秒的时间吧。数据再大就堆栈溢出了。