今日头条2018校招编程题思路
第一题,串珠
颜色用二进制存储。枚举颜色后twp-point/滑动窗口解决。 每次往右边加进来一个点判断该点是否存在目前枚举的颜色,存在cnt++; 弹出最左边的点,如果最左边的点存在目前枚举的颜色,cnt--。如果cnt>1. ans++。
复杂度O(n)
#include<iostream> #include<cstring> #include<string> #include<algorithm> #include<stdio.h> #include<queue> #include<vector> #include<stack> #include<map> #include<set> #include<bitset> #include<time.h> #include<cmath> #include<sstream> #include<assert.h> using namespace std; typedef long long int LL; const LL INF = 0x7FFFFFFFFFFFFFFF; const int inf = 0x3f3f3f3f; const int MAXN = 10000 + 1024; LL col[MAXN * 2]; int main(){ int n, m, c; while (~scanf("%d%d%d", &n, &m, &c)){ memset(col, 0, sizeof(col)); for (int i = 1; i <= n; i++){ int Size, val; scanf("%d", &Size); for (int j = 1; j <= Size; j++){ scanf("%d", &val); col[i] |= (1LL << val); } col[i + n] = col[i]; } if (m > n){ printf("0\n"); } else{ int ans = 0; for (int k = 1; k <= c; k++){ int cnt = 0; bool flag = false; for (int i = 1; i <= m; i++){ if (col[i] & (1LL << k)){ cnt++; } } if (cnt > 1){ flag = true; } for (int i = m + 1; i <= n * 2 && i - m <= n && !flag; i++){ if (col[i - m] & (1LL << k)){ cnt--; } if (col[i] & (1LL << k)){ cnt++; } if (cnt > 1){ flag = true; } } if (flag){ ans++; } } printf("%d\n", ans); } } return 0; }
第二题, 区间内k值的多少
离线处理,把询问全部读入,分块排序询问,用map来维护某个值出现的次数,莫队转移。
复杂度O(q*sqrt(n)*log(n))
另外一种方式是离散化k,然后对于每个k用一个vector保存值为k的人的下标。对于询问我们可以定位到vector[k]这个数组,然后用二分查找看有多少个人在[l,r]之间。
复杂度O(n*log(n)+q*log(n))
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<queue> #include<map> #include<vector> #include<cmath> using namespace std; typedef long long int LL; const int MAXN = 300000+1024; int be[MAXN], ans[MAXN]; LL a[MAXN]; map<LL, int> mp; struct Qry{ int l, r, id; LL k; bool operator<(const Qry &o)const{ if (be[l] == be[o.l]) return (be[l] & 1) ? r > o.r:r < o.r; return l < o.l; } }Q[MAXN]; void add(LL x){ mp[x]++; } void del(LL x){ mp[x]--; } int main(){ #ifdef kirito freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); #endif int n, q; while (~scanf("%d", &n)){ int S = (int)sqrt(n + 0.5); for (int i = 0; i <= n; ++i) be[i] = i / S; for (int i = 1; i <= n; ++i) scanf("%lld",&a[i]); scanf("%d", &q); for (int i = 0; i < q; ++i){ scanf("%d%d%lld", &Q[i].l, &Q[i].r, &Q[i].k); Q[i].id = i; } sort(Q, Q + q); for (int i = 0, l = 1, r = 0; i < q; ++i){ while (r < Q[i].r) add(a[++r]); while (l > Q[i].l) add(a[--l]); while (l < Q[i].l) del(a[l++]); while (r > Q[i].r) del(a[r--]); ans[Q[i].id] = mp[Q[i].k]; } for (int i = 0; i < q; ++i){ printf("%d\n", ans[i]); } } return 0; }
第三题,字符串相邻字符交换有限次数,得到最长的连续相同字符长度
枚举每种字母,计算该字母在字符串中出现的位置。再枚举以该字符每个位置为中心点,两边的字符往这个中心靠拢,计算一个距离的前缀和, 再枚举左端点,二分找右端点。
复杂度O(26*|s|*|s|*log(|s|))
#define _CRT_SECURE_NO_DEPRECATE #include<iostream> #include<cstring> #include<string> #include<algorithm> #include<stdio.h> #include<queue> #include<vector> #include<stack> #include<map> #include<set> #include<bitset> #include<time.h> #include<cmath> #include<sstream> #include<assert.h> using namespace std; typedef long long int LL; const LL INF = 0x7FFFFFFFFFFFFFFF; const int inf = 0x3f3f3f3f; const int MAXN = 10000 + 1024; char str[MAXN]; vector<int>pos; int dst[MAXN],preSum[MAXN]; int main(){ #ifdef kirito freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); #endif int m; while (~scanf("%s%d", str, &m)){ int len = strlen(str); int ans = 0; for (int i = 0; i < 26; i++){ pos.clear(); for (int j = 0; j < len; j++){ if (str[j] == ('a' + i)){ pos.push_back(j); } } int Size = pos.size(); for (int j = 0; j < Size; j++){ memset(dst, 0, sizeof(dst)); memset(preSum, 0, sizeof(preSum)); for (int _j = 0; _j < Size; _j++){ dst[_j] = abs(pos[_j] - pos[j]); } for (int _j = j + 1; _j < Size; _j++){ preSum[_j] = preSum[_j - 1] + dst[_j] - (_j - j); } for (int _j = j - 1; _j >= 0; _j--){ preSum[_j] = preSum[_j + 1] + dst[_j] - (j - _j); } preSum[Size] = inf; for (int _j = j; _j >= 0; _j--){ int need = m - preSum[_j]; if (j + 1 >= Size){ continue; } int pos = upper_bound(preSum + j + 1, preSum + Size,need) - preSum; pos--; if (pos >= j + 1 && pos < Size){ ans = max(ans, pos - j + 1 + (j - _j)); } } } } printf("%d\n", ans); } return 0; }
#字节跳动#