好久没有题解了,原因是:我太菜了!上次国庆放假的时候,也就是10月2号上午,参加leetcode周赛,我只做出来2道easy的,剩下2道medium没有做出来(我记得以前是medium,刚才看了一下,怎么变成hard了?)。那时候我感觉好失落,自己真菜,水平真次,每天还爱装逼,感觉还写什么题解,真是笑掉大牙!刚好前一天的晚上cf也只做出来一道题,我也就2道题的水平,第一道题由于把‘1’写成1,一直没有检查出来!所以,那一刻,心里真不是滋味!刚好前天去面wap,也被刷了,我认为主要原因是英语太差,跟面试官交流非常困难,还有那个树形dp没有搞出来,哎,也就这样吧!
第一题:获取数字,随机输入自然数n,对每个测试实例,要求输出大于n的下一个对称数字。输入451 3840 3363 999,输出454 3883 3443 1001.
分析:要大于n,简单往上加1,然后判断是不是对称的,会过某些用例,但会tle,还有这题没给数据范围,自然数,那就可能非常大,只能通过string来出来,下面找规律。
1. 首先我考虑(都把数字当做字符串来考虑),输入长度,除了全部为9的情况,剩下的输出长度应该跟输入长度一致。为什么,仔细想一想。
2. 下面只考虑奇数长度,暂时不考虑偶数(偶数比奇数长度比较容易处理),这样输入s = s1as2,把输入分解成字符串s1,s2和中间字符a。简单的想法,如果把s1翻转,如果比s2大,显然是满足情况的,而且这也是大于输入的对称的最小的数。
3. 用s1t表示s1的翻转,如果s2大于s1t,那么翻转过去构成的对称的数字就会小于输入的自然后,然后考虑改变,这时候最小的改变就是从a开始,只需要把a加1即可,如果a已经最大,比如9,这时候就要考虑增大s1,只需要简单的把s1增大一点点,然后就可以了,
同时,为了保持最小,有些位置需要设置为0,比如(13941),这里s1=13,s2=41,a=9,s1t = 31,s2 > s1t,需要增大,这时候a无法增大,只能增大s1,s1 = 14,如果a不变,结果就是14941,但是为了最小,14041,也是满足要求的对称自然数。然后就结束了。
下面贴上我的代码,写的有点丑,我就不修改了,反正ac了。我分的情况比较多,其实一些情况可以合并。
1 /* 2 ID: y1197771 3 PROG: test 4 LANG: C++ 5 */ 6 #include<bits/stdc++.h> 7 #define pb push_back 8 #define FOR(i, n) for (int i = 0; i < (int)n; ++i) 9 #define dbg(x) cout << #x << " at line " << __LINE__ << " is: " << x << endl 10 typedef long long ll; 11 using namespace std; 12 typedef pair<int, int> pii; 13 const int maxn = 1e3 + 10; 14 void solve() { 15 string s; 16 while(cin >> s) { 17 int n = s.size(); 18 int cnt = 0; 19 for (char ch : s) { 20 cnt += ch == '9'; 21 } 22 string res; 23 if(cnt == n) { 24 res = "1"; 25 res.append(n - 1, '0'); 26 res.append(1, '1'); 27 cout << res << endl; 28 continue; 29 } 30 if(n & 1) { 31 string s1 = s.substr(0, n / 2); 32 string s2 = s.substr(n / 2 + 1); 33 reverse(s1.begin(), s1.end()); 34 if(s2 > s1) { 35 if(s[n / 2] == '9') { 36 s[n / 2] = '0'; 37 for (int i = 0; i < n / 2; i++) { 38 if(s1[i] != '9') { 39 s1[i] = s1[i] + 1; 40 break; 41 } else s1[i] = '0'; 42 } 43 } else { 44 s[n / 2] = s[n / 2] + 1; 45 } 46 res = s1; 47 res.insert(0, 1, s[n / 2]); 48 reverse(s1.begin(), s1.end()); 49 res = s1 + res; 50 } else if(s1 == s2) { 51 if(s[n / 2] == '9') { 52 s[n / 2] = '0'; 53 for (int i = 0; i < n / 2; i++) { 54 if(s1[i] != '9') { 55 s1[i] = s1[i] + 1; 56 break; 57 } else s1[i] = '0'; 58 } 59 } else { 60 s[n / 2] = s[n / 2] + 1; 61 } 62 res = s1; 63 res.insert(0, 1, s[n / 2]); 64 reverse(s1.begin(), s1.end()); 65 res = s1 + res; 66 } else { 67 res = s.substr(0, n / 2 + 1); 68 res = res + s1; 69 } 70 } else { 71 string s1 = s.substr(0, n / 2); 72 string s2 = s.substr(n / 2); 73 reverse(s1.begin(), s1.end()); 74 if(s2 > s1) { 75 for (int i = 0; i < n / 2; i++) { 76 if(s1[i] != '9') { 77 s1[i] = s1[i] + 1; 78 break; 79 } else s1[i] = '0'; 80 } 81 res = s1; 82 reverse(s1.begin(), s1.end()); 83 res = s1 + res; 84 } else if(s1 == s2) { 85 for (int i = 0; i < n / 2; i++) { 86 if(s1[i] != '9') { 87 s1[i] = s1[i] + 1; 88 break; 89 } else s1[i] = '0'; 90 } 91 res = s1; 92 reverse(s1.begin(), s1.end()); 93 res = s1 + res; 94 } else { 95 res = s.substr(0, n / 2) + s1; 96 } 97 } 98 cout << res << endl; 99 } 100 } 101 int main() { 102 //freopen("test.in", "r", stdin); 103 //freopen("test.out", "w", stdout); 104 solve(); 105 return 0; 106 }
第二题: 字符串,给定两个均由大写英文字母组成的字符串(A-Z),检查这两个字符串是否包含相同的字母。
水题,直接写。
1 /* 2 ID: y1197771 3 PROG: test 4 LANG: C++ 5 */ 6 #include<bits/stdc++.h> 7 #define pb push_back 8 #define FOR(i, n) for (int i = 0; i < (int)n; ++i) 9 #define dbg(x) cout << #x << " at line " << __LINE__ << " is: " << x << endl 10 typedef long long ll; 11 using namespace std; 12 typedef pair<int, int> pii; 13 const int maxn = 1e3 + 10; 14 void solve() { 15 string s1, s2; 16 vector<bool> v1(26, 0), v2(26, 0); 17 while(cin >> s1 >> s2) { 18 for (char x : s1) { 19 v1[x - 'A'] = 1; 20 } 21 for (char x : s2) { 22 v2[x - 'A'] = 1; 23 } 24 bool f = 0; 25 for (int i = 0; i < 26; i++) { 26 if(v1[i] != v2[i]) { 27 f = 1; 28 break; 29 } 30 } 31 if(f) cout << "false" << endl; 32 else cout << "true" << endl; 33 } 34 } 35 int main() { 36 //freopen("test.in", "r", stdin); 37 //freopen("data", "w", stdout); 38 solve(); 39 return 0; 40 }
第三题:最终收敛值,没有做出来,我用的multiset不断模型,(刚开始用set,才发现有重复元素),这个代码就不贴了,写的太烂。
第四题:
这个题是某某科技现场做的笔试题,不会做!
题意大概是有n个数组,每个数组4个数字,要求每个数字取一个数字,然后加起来,这样的方式一共有4^n种,把这些数字从小到大排序,输出第k大的数字。
函数签名大概是 int findkthnumber(int a[N][4], int n, int k);
没思路,没想法,不会做。如果有想法,求告知!