9-10月刷题Keep On

看到日期有点慌啊……趁着这几天准备笔试,抓住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 << "\n";
 83         }
 84     }
 85 
 86     fout << "\n";
 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 }
View Code
复制代码

 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 << "\n";
 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 }
View Code
复制代码

 【字符串】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 << "\n";
45 
46     fout.close();
47 
48     return 0;
49 }
View Code
复制代码

 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(), '\n');
54 
55     string s;
56     getline(cin, s);
57 
58     long result = substrCount(n, s);
59 
60     fout << result << "\n";
61 
62     fout.close();
63 
64     return 0;
65 }
View Code
复制代码

 

posted on   Mju_halcyon  阅读(134)  评论(0编辑  收藏  举报

编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示