PAT1005 继续(3n+1)猜想 (25 分)【vector erase需要注意的地方】
心得
無論在任何時候,使用vector的erase方法時需要謹慎再謹慎。
無論是使用數組的形式arr[i]進行遍歷,還是使用iter迭代器遍歷,在使用erase后,原來的位置都可能會失效。因為這種遍歷刪除可能會觸碰到當前元素i(或iter)之前的元素,也就改變了i(或者iter)的絕對位置,雖然i沒變,但是arr[i]指向的數變了!
這導致跳過了某些vector arr數值沒有判斷,或者直接iter失效,也就是將一個無效的值賦值給了將無效函數視為嚴重錯誤的函數。
對于本體的解法,原思路的bug在于,如果刪除了一個i之前的元素,會讓i的絕對位置后移一位,跳過了之前那一位的判斷。
因此在本題中的解決方法是:迷之25行的對于debugger定義
將錯就錯,跳過一個判斷就跳過判斷吧,就暫且讓那些該被刪除的數多活一個循環。以后在處理這些數也不晚。
我把整個過程重復arr.size()次,就算是每次都跳過了一個arr[i]的判斷,但至少在這次中肯定會至少刪除一個該刪的元素。然后重復arr.size()次以后,那些被跳過的也補回來了。
其他解決方法
其他方法解決vector中刪除的元素是當前元素之前的元素的問題:
1.用鏈表,pcur指向當前元素(絕對位置)。指針的位置不會因為刪除任何位置的元素而改變。
2.賦異常值。如果刪除一個元素,將這個元素賦值為-1,最后再遍歷刪除所有值為-1的元素(原理同樣是保持相對位置或者說絕對位置不變)
3.動態調整i
刪除元素的時候,如果要刪除的元素的位置j<i,則i--
題目
卡拉茲(Callatz)猜想已經在1001中給出了描述。在這個題目里,情況稍微有些復雜。
當我們驗證卡拉茲猜想的時候,為了避免重復計算,可以記錄下遞推過程中遇到的每一個數。例如對 n=3 進行驗證的時候,我們需要計算 3、5、8、4、2、1,則當我們對 n=5、8、4、2 進行驗證的時候,就可以直接判定卡拉茲猜想的真偽,而不需要重復計算,因為這 4 個數已經在驗證3的時候遇到過了,我們稱 5、8、4、2 是被 3“覆蓋”的數。我們稱一個數列中的某個數 n 為“關鍵數”,如果 n 不能被數列中的其他數字所覆蓋。
現在給定一系列待驗證的數字,我們只需要驗證其中的幾個關鍵數,就可以不必再重復驗證余下的數字。你的任務就是找出這些關鍵數字,并按從大到小的順序輸出它們。
輸入格式:
每個測試輸入包含 1 個測試用例,第 1 行給出一個正整數 K (<100),第 2 行給出 K 個互不相同的待驗證的正整數 n (1<n≤100)的值,數字間用空格隔開。
輸出格式:
每個測試用例的輸出占一行,按從大到小的順序輸出關鍵數字。數字間用 1 個空格隔開,但一行中最后一個數字后沒有空格。
輸入樣例:
6
3 5 6 7 8 11
輸出樣例:
7 6
代碼
//把每一個元素都算一遍,過程中遇到的數如果有和給定數組中相同的,刪除數組中的數。這樣,數組中最后剩下的就是關鍵數 #define _CRT_SRCURE_NO_WARNINS #include<iostream> #include<vector> #include<algorithm> using namespace std; int main() {int total;cin >> total;//輸入vectorvector<int>arr;int num;int i;for (i = 0; i < total; i++){cin >> num;arr.push_back(num);}//計算每個元素,刪除重復的sort(arr.begin(), arr.end());int n;int j;int debugger = arr.size();for (; debugger >= 0; debugger--){for (i = 0; i < arr.size(); i++){//計算nn = arr[i];while (n != 1){if (n % 2 == 0){n /= 2;}else{n = (3 * n + 1) / 2;}//刪除n(不能刪除a[i]本身,但不避免a[i]重復的可能)for (j = 0; j < arr.size(); j++){if (arr[j] == n ){arr.erase(arr.begin() + j);}}}}}//刪除重復元素sort(arr.begin(), arr.end()); //unique只能比較相鄰元素是否重復arr.erase(unique(arr.begin(), arr.end()), arr.end()); //unique將重復的元素移到末尾,返回末尾中第一個重復值的地址//21//3 5 6 7 8 11 12 4 5 6 7 8 9 10 11 12 13 14 15 16 17for (i = arr.size() - 1; i >= 0; i--){cout << arr[i];if (i != 0)cout << ' ';}system("pause");return 0; }總結
以上是生活随笔為你收集整理的PAT1005 继续(3n+1)猜想 (25 分)【vector erase需要注意的地方】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C语言 课设 最新版 学生成绩管理系统
- 下一篇: PAT1006 换个格式输出整数