• 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 << "
    ";
     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 }
    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 << "
    ";
     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 << "
    ";
    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(), '
    ');
    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 }
    View Code
    用代码改变世界!就是这样,喵!
  • 相关阅读:
    洛谷 P1291 [SHOI2002]百事世界杯之旅 解题报告
    洛谷 P1338 末日的传说 解题报告
    洛谷 P3952 时间复杂度 解题报告
    vector-erase
    STL之--插入迭代器(back_inserter,inserter,front_inserter的区别
    STL之--插入迭代器(back_inserter,inserter,front_inserter的区别
    vector-end
    vector-end
    vector-empty
    vector-empty
  • 原文地址:https://www.cnblogs.com/Song-Meow/p/13744173.html
Copyright © 2020-2023  润新知