南大算法設計與分析課程OJ答案(2)
阿新 • • 發佈:2018-03-24
sam long bmi 窮舉 bbbb body 算法設計 分配 info
提交: 184 解決: 66
提交 狀態 算法問答
) 的算法。這兩個算法將會超時。
利用分治的思想可以有 O(n*logn) 的算法。
也有聰明的算法,它的復雜度是 O(n) 的。
另請註意:輸入多少個數是未知的。請思考如何處理。
提交: 289 解決: 49
提交 狀態 算法問答
問題 A: 最大子序列和問題
時間限制: 1 Sec 內存限制: 4 MB提交: 184 解決: 66
提交 狀態 算法問答
題目描述
給定一整數序列 a1, a2, …, an,求 a1~an 的一個子序列 ai~aj,使得從 ai 到 aj 的和最大。
只需要求出最大子序列的和,而不需要求出最大的那個序列。
輸入
一組整數,數字和數字之間以空格隔開。輸出
該整數序列中最大子序列的和
樣例輸入-2 11 -4 13 -5 -2
|
樣例輸出20
|
提示
應用窮舉法可以得到 O(n3) 的算法,優化它即可得到 O(n2利用分治的思想可以有 O(n*logn) 的算法。
也有聰明的算法,它的復雜度是 O(n) 的。
另請註意:輸入多少個數是未知的。請思考如何處理。
答案看這裏
http://www.cnblogs.com/likaiming/p/8570205.html問題 B: 所有的逆序對
時間限制: 2 Sec 內存限制: 5 MB提交: 289 解決: 49
提交 狀態 算法問答
題目描述
給出一個字符串數組,如果(按照字典序)一個大的字符串在比它小的字符串前面我們稱這兩個字符串組成一個“逆序對”。你需要找到所有的逆序對的個數。
輸入
第一行是數組大小,第二行是以空格分隔的字符串數組.
註:預先知道每個字符串的長度都是 10.
輸出
所有的逆序對個數. 這次需要大家先輸出一個字符串,它是“我已閱讀關於抄襲的說明”的漢語拼音.輸出此行的提交我們將認為已經完全閱讀並了解了“關於抄襲的說明”公告.
註意:結果比較大,請用 long 類型保存.
樣例輸入3
aaaaaaaaaa cccccccccc bbbbbbbbbb
|
樣例輸出wo yi yue du guan yu chao xi de shuo ming
1
|
提示
不要使用蠻力算法
答案
暴力解法,會超時
long long a(vector<stringbf>& v, int pos1, int pos2) { long long w = 0; for (int i = pos1; i <= pos2; ++i) { for (int j = i + 1; j <= pos2; ++j) { if (v[i] > v[j]) ++w; } } return w; }
歸並排序的思想,只需要在歸並排序的基礎之上加上一個統計量,和一行代碼,但是下面的做法會超出內存限制
void merge(vector<string>& v, int pos1, int mid, int pos2, long long& nums) { //從0開始的數組,如果兩個位置分別為p1和p2,其中p1<p2,則p1到p2距離的元素有p2-p1+1個 vector<string> n1 (v.begin()+pos1,v.begin()+mid+1); vector<string> n2 (v.begin()+mid+1,v.begin()+pos2+1); n1.emplace_back("zzzzzzzzzzzzzzzzzzzz"); n2.emplace_back("zzzzzzzzzzzzzzzzzzzz"); int n1_pos = 0; int n2_pos = 0; for (int i = pos1; i <= pos2;++i) { if (n1[n1_pos] <= n2[n2_pos]) { v[i] = n1[n1_pos]; ++n1_pos; }else{ //在這加上統計量 nums += n1.size() - n1_pos-1; v[i] = n2[n2_pos]; ++n2_pos; } } } void mergesort(vector<string>& v, int pos1, int pos2, long long& nums) { if (pos1 < pos2) { int mid = (pos1 + pos2) / 2; mergesort(v,pos1,mid,nums); mergesort(v,mid+1,pos2,nums); merge(v,pos1,mid,pos2,nums); } } //這是測試用例 int main() { int nums = 0; cin >> nums; string temp; vector<string> v(nums,""); for (int i = 0; i < nums; ++i) { cin >> temp; v[i] = temp; } vector<string> v = { "aaaaaaaaaa", "cccccccccc", "bbbbbbbbbb" }; long long result = 0; mergesort(v, 0, v.size() - 1, result); cout << "wo yi yue du guan yu chao xi de shuo ming" << endl; cout << result << endl; //system("pause"); return 0; }歸並解法
經大佬提醒,不在遞歸時分配vector,而是在開始遞歸之前申請一個help的vector用來幫助歸並排序,這樣可以減小內存使用,但是上面使用哨兵的方法就不能用了,代碼稍微復雜了一些,但任然是歸並排序加上一行統計代碼。
void merge(vector<string>& v, int pos1, int mid, int pos2, long long& nums, vector<string>& help) { //從0開始的數組,如果兩個位置分別為p1和p2,其中p1<p2,則p1到p2距離的元素有p2-p1+1個 for (int i = pos1; i <= pos2; ++i) help[i] = v[i]; int n1_pos = pos1; int n2_pos = mid+1; for (int i = pos1; i <= pos2;++i) { //當一個數組已經遍歷完成時 if (n1_pos == mid + 1) { while (n2_pos != pos2 + 1) { v[i++] = help[n2_pos++]; } break; } if (n2_pos == pos2 + 1) { while (n1_pos != mid + 1) { v[i++] = help[n1_pos++]; } break; } //其他情況 if (help[n1_pos] <= help[n2_pos]) { v[i] = help[n1_pos]; ++n1_pos; }else{ //在這加上統計量 nums += mid-n1_pos+1; v[i] = help[n2_pos]; ++n2_pos; } } } void mergesort(vector<string>& v, int pos1, int pos2, long long& nums,vector<string>& help) { if (pos1 < pos2) { int mid = (pos1 + pos2) / 2; mergesort(v,pos1,mid,nums,help); mergesort(v,mid+1,pos2,nums,help); merge(v,pos1,mid,pos2,nums,help); } } //這是測試用例 int main() { int nums = 0; cin >> nums; string temp; vector<string> v(nums,""); for (int i = 0; i < nums; ++i) { cin >> temp; v[i] = temp; } //vector<string> v = { "4","3","2","1" }; vector<string> help(v.size()," "); long long result = 0; mergesort(v, 0, v.size() - 1, result,help); cout << "wo yi yue du guan yu chao xi de shuo ming" << endl; cout << result << endl; system("pause"); return 0; }歸並排序內存優化
南大算法設計與分析課程OJ答案(2)