看到日期有点慌啊……趁着这几天准备笔试,抓住9月的尾巴补一篇随笔
9.28
【字符串】Sherlock - HackerRank
Manacher算法(“马拉车”算法)
尴尬……上面这道题好像不能直接用马拉车算法,我至今也没弄出来
10.2
【字典/哈希】Frequency Queries - HackerRank
可能太久没做题了,逻辑半天都捋不清楚!此题的关键是维护两个Map,这样可以有两个键名供查找。易错点是注意增删操作影响的元素频数,且需要判断Map中没有该元素的两种情况(根本没有对应的键,或键名对应的值为0)
参考代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 string ltrim(const string &); 4 string rtrim(const string &); 5 vector<string> split(const string &); 6 7 // Complete the freqQuery function below. 8 vector<int> freqQuery(vector<vector<int>> queries) { 9 unordered_map<int, int> UMp1;//事后发现此题的时间效率与是否是哈希的map好像没关系,只要是字典O(1)查找就行 10 unordered_map<int, int> UMp2; 11 vector<int> ans; 12 int len = queries.size(); 13 for(int i = 0; i < len; i++){ 14 int op = queries[i][0], ob = queries[i][1]; 15 if(op == 1){ 16 if(UMp1.find(ob) != UMp1.end() && UMp1[ob] != 0){ 17 UMp1[ob] ++; 18 if(UMp2.find(UMp1[ob]) != UMp2.end() && UMp2[UMp1[ob]] != 0){ 19 UMp2[ UMp1[ob] ] ++; 20 } 21 else UMp2[ UMp1[ob] ] = 1; 22 UMp2[ UMp1[ob]-1 ] --; 23 } 24 else{ 25 UMp1[ob] = 1; 26 if(UMp2.find(1) != UMp2.end() && UMp2[1] != 0){ 27 UMp2[1] ++; 28 } 29 else UMp2[1] = 1; 30 } 31 } 32 else if(op == 2){ 33 if(UMp1.find(ob) != UMp1.end() && UMp1[ob] != 0){ 34 UMp1[ob] --; 35 if(UMp2.find(UMp1[ob]) != UMp2.end() && UMp2[UMp1[ob]] != 0) UMp2[ UMp1[ob] ] ++; 36 else{ 37 UMp2[ UMp1[ob] ] = 1; 38 } 39 if(UMp2[UMp1[ob]+1] > 0) UMp2[ UMp1[ob]+1 ] --; 40 } 41 } 42 else if(op == 3){ 43 if(UMp2.find(ob) == UMp2.end() || UMp2[ob] == 0) ans.push_back(0); 44 else ans.push_back(1); 45 } 46 } 47 return ans; 48 } 49 50 int main() 51 { 52 ofstream fout(getenv("OUTPUT_PATH")); 53 54 string q_temp; 55 getline(cin, q_temp); 56 57 int q = stoi(ltrim(rtrim(q_temp))); 58 59 vector<vector<int>> queries(q); 60 61 for (int i = 0; i < q; i++) { 62 queries[i].resize(2); 63 64 string queries_row_temp_temp; 65 getline(cin, queries_row_temp_temp); 66 67 vector<string> queries_row_temp = split(rtrim(queries_row_temp_temp)); 68 69 for (int j = 0; j < 2; j++) { 70 int queries_row_item = stoi(queries_row_temp[j]); 71 72 queries[i][j] = queries_row_item; 73 } 74 } 75 76 vector<int> ans = freqQuery(queries); 77 78 for (int i = 0; i < ans.size(); i++) { 79 fout << ans[i]; 80 81 if (i != ans.size() - 1) { 82 fout << " "; 83 } 84 } 85 86 fout << " "; 87 88 fout.close(); 89 90 return 0; 91 } 92 93 string ltrim(const string &str) { 94 string s(str); 95 96 s.erase( 97 s.begin(), 98 find_if(s.begin(), s.end(), not1(ptr_fun<int, int>(isspace))) 99 ); 100 101 return s; 102 } 103 104 string rtrim(const string &str) { 105 string s(str); 106 107 s.erase( 108 find_if(s.rbegin(), s.rend(), not1(ptr_fun<int, int>(isspace))).base(), 109 s.end() 110 ); 111 112 return s; 113 } 114 115 vector<string> split(const string &str) { 116 vector<string> tokens; 117 118 string::size_type start = 0; 119 string::size_type end = 0; 120 121 while ((end = str.find(" ", start)) != string::npos) { 122 tokens.push_back(str.substr(start, end - start)); 123 124 start = end + 1; 125 } 126 127 tokens.push_back(str.substr(start)); 128 129 return tokens; 130 }
10.3
【排序】Fraudulent Activity Notifications - HackerRank
通过此题首次接触到了基数排序和计数排序!(暂时没空自己总结了,贴两篇博文链接好了。)这题还是有点东西滴~
另外,桶排序是计数排序的优化版本,记得补上。
参考代码:
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 vector<string> split_string(string); 6 7 // Complete the activityNotifications function below. 8 int activityNotifications(vector<int> expenditure, int d) { 9 int n = expenditure.size(), cnt = 0, Max = -1, Min = 300; 10 for(int i = 0; i < n; ++i){ 11 Max = max(Max, expenditure[i]); 12 Min = min(Min, expenditure[i]); 13 } 14 vector<int> votes(Max - Min + 1);//从最小到最大数,以最小数为基准。此题的范围是0-200,故桶排序很高效 15 if(d%2 == 1){ 16 for(int i = 0; i < d; ++i){ 17 votes[expenditure[i] - Min] ++; 18 } 19 for(int i = d; i < n; ++i){ 20 int k = d/2+1, j = -1;//计算中位数的区间长度d为奇数时,就遍历到前d/2+1个数 21 while(k > 0){ 22 j ++; 23 k -= votes[j]; 24 } 25 if(expenditure[i] >= 2 * (j+Min)) cnt ++;//后面不要忘了每次计算引用下标都要调整一个最小数 26 votes[ expenditure[i - d] - Min] --; 27 votes[ expenditure[i] - Min] ++; 28 } 29 } 30 else{ 31 for(int i = 0; i < d; ++i){ 32 votes[expenditure[i] - Min] ++; 33 } 34 for(int i = d; i < n; ++i){ 35 int k = d/2, j = -1, tmp = 0;//对于d是偶数的情况,分两次取两个k,用tmp记录和的值 36 while(k > 0){ 37 j ++; 38 k -= votes[j]; 39 } 40 tmp += j + Min; 41 if(k<0) tmp *= 2;//如果这两个中间数相同,则k一定会减为负数 42 else{ 43 k = 1; //如果不同,k再向后取一个 44 while(k > 0){ 45 j ++; 46 k -= votes[j]; 47 } 48 tmp += j + Min; 49 } 50 if(expenditure[i] >= tmp) cnt ++; 51 votes[ expenditure[i - d] - Min] --; 52 votes[ expenditure[i] - Min] ++; 53 } 54 } 55 return cnt; 56 } 57 58 int main() 59 { 60 ofstream fout(getenv("OUTPUT_PATH")); 61 62 string nd_temp; 63 getline(cin, nd_temp); 64 65 vector<string> nd = split_string(nd_temp); 66 67 int n = stoi(nd[0]); 68 69 int d = stoi(nd[1]); 70 71 string expenditure_temp_temp; 72 getline(cin, expenditure_temp_temp); 73 74 vector<string> expenditure_temp = split_string(expenditure_temp_temp); 75 76 vector<int> expenditure(n); 77 78 for (int i = 0; i < n; i++) { 79 int expenditure_item = stoi(expenditure_temp[i]); 80 81 expenditure[i] = expenditure_item; 82 } 83 84 int result = activityNotifications(expenditure, d); 85 86 fout << result << " "; 87 88 fout.close(); 89 90 return 0; 91 } 92 93 vector<string> split_string(string input_string) { 94 string::iterator new_end = unique(input_string.begin(), input_string.end(), [] (const char &x, const char &y) { 95 return x == y and x == ' '; 96 }); 97 98 input_string.erase(new_end, input_string.end()); 99 100 while (input_string[input_string.length() - 1] == ' ') { 101 input_string.pop_back(); 102 } 103 104 vector<string> splits; 105 char delimiter = ' '; 106 107 size_t i = 0; 108 size_t pos = input_string.find(delimiter); 109 110 while (pos != string::npos) { 111 splits.push_back(input_string.substr(i, pos - i)); 112 113 i = pos + 1; 114 pos = input_string.find(delimiter, i); 115 } 116 117 splits.push_back(input_string.substr(i, min(pos, input_string.length()) - i + 1)); 118 119 return splits; 120 }
【字符串】Sherlock And Valid String - HackerRank
这题也好细节啊……天。
参考代码:
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 // Complete the isValid function below. 6 string isValid(string s) { 7 int n = s.size(); 8 int type[26]; 9 memset(type, 0 ,sizeof(type)); 10 for(int i = 0; i < n; ++i){ 11 type[s[i]-'a'] ++; 12 } 13 int k1 = 0, k2 = 0, n1 = 0, n2 = 0; 14 for(int i = 0; i < 26; ++i){ 15 if(n1 > 1 && n2 > 1) return "NO";//出现两种占主重复次数 16 if(n1 == 1 && n2 > 1 && k1 != k2+1 && k1 != 1) return "NO";//出现两种无法调和的重复次数(无法通过-1合并为同一次数或降低字母多样性) 17 if(n2 == 1 && n1 > 1 && k2 != k1+1 && k2 != 1)return "NO"; 18 if(type[i] > 0){//type[i]是字母('a'+i)的出现次数 19 if(type[i] == k1) n1++; 20 else if(type[i] == k2) n2++; 21 else if(k1 == 0){ 22 k1 = type[i]; 23 n1 = 1; 24 } 25 else if(k2 == 0){ 26 k2 = type[i]; 27 n2 = 1; 28 } 29 else return "NO";//出现三种重复次数 30 } 31 } 32 return "YES"; 33 } 34 35 int main() 36 { 37 ofstream fout(getenv("OUTPUT_PATH")); 38 39 string s; 40 getline(cin, s); 41 42 string result = isValid(s); 43 44 fout << result << " "; 45 46 fout.close(); 47 48 return 0; 49 }
10.4
【字符串】Special String Again - HackerRank
O(1)复杂度的解法↓ [呲牙][呲牙]
参考代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 // Complete the substrCount function below. 4 long substrCount(int n, string s) { 5 long cnt = 0; 6 //Save trailing numbers 7 vector<int> trail(n); 8 char pre = s[0]; 9 trail[0] = 1; 10 for(int i = 1; i <n; ++i){ 11 if(s[i] == pre){ 12 trail[i] = trail[i - 1] + 1; 13 } 14 else{ 15 pre = s[i]; 16 trail[i] = 1; 17 } 18 } 19 //Save trailing numbers of the reverse order 20 vector<int> rev_trail(n); 21 char rev_pre = s[n-1]; 22 rev_trail[n-1] = 1; 23 for(int i = n-2; i >= 0; --i){ 24 if(s[i] == rev_pre){ 25 rev_trail[i] = rev_trail[i + 1] + 1; 26 } 27 else{ 28 rev_pre = s[i]; 29 rev_trail[i] = 1; 30 } 31 } 32 //Calculate pattern 1 33 for(int i = 0; i < n; ++i){ 34 if(i + 1 < n && trail[i] < trail[i+1]) continue; 35 cnt += trail[i] * (trail[i] + 1) / 2; 36 } 37 //Calculate pattern 2 38 for(int i = 1; i < n - 1; ++i){ 39 if(s[i-1] == s[i+1] && trail[i] == 1){ 40 int l1 = trail[i-1], l2 = rev_trail[i+1]; 41 cnt += min(l1, l2); 42 } 43 } 44 return cnt; 45 } 46 47 int main() 48 { 49 ofstream fout(getenv("OUTPUT_PATH")); 50 51 int n; 52 cin >> n; 53 cin.ignore(numeric_limits<streamsize>::max(), ' '); 54 55 string s; 56 getline(cin, s); 57 58 long result = substrCount(n, s); 59 60 fout << result << " "; 61 62 fout.close(); 63 64 return 0; 65 }