字节跳动(今日头条)算法岗笔试 03.16 AK题解

第一题,大水题,直接上代码:
n, answer = 1024-int(input()), 0
for coin in [64, 16, 4, 1]:
  answer += n // coin
  n = n % coin
print(answer)
第二题,比较简单,题目的中的两个判断条件,都只跟前2-3位字符有关。
思路:逐个判断字符,根据两个条件判断是否可以加到结果字符串中
代码:


def solve(s):
    n = len(s)
    r = list(s[:min(len(s), 2)])
    for i in range(2, n):
        if s[i] == r[-1] == r[-2]:
            continue
        if s[i] == r[-1] and len(r) > 2 and r[-2] == r[-3]:
            continue
        r.append(s[i])
    return ''.join(r)
            
for test_case in range(int(input())):
    print(solve(input()))
第三题,Python挂掉,C++通过(不知道为什么字体变色了- -
思路:从未分配奖品的人中选取分数最小的人,然后判断她两边的人是否分配了奖品
情况1. 如果两边都已经分配奖品,当前位置的分数肯定比两边大(结合情况2,即可简单证明),此时取两边奖品最大值+1即可。
情况2. 如果有未分配奖品的方向:当前位置分配奖品数1,沿着未分配的方向,依次分配,直到当前结点大于后继结点。
比如:分数 为 1 -> 2 -> 2 -> 5 -> 3
那么:奖品 为 1 -> 2 -> 1 -> 不分配 (遇到相同可以重置为1)
多说一句,如果一个方向分配,另一个方向未分配,则分配过奖品方向的那个位置的分数,肯定比当前位置大,可简单证明。
依次取分数最小的位置,不断遍历即可,复杂度(排序 NlogN, 遍历O(n)),故NlogN
代码,python 只过了11%数据,只好用C++重写了一遍:
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
int t, n, x;
vector< pair<int, int> > a;
vector<int> b,v;
inline int left(int index){
    if(index == n - 1)
        return 0;
    return index + 1;
}
inline int right(int index){
    if(index == 0)
        return n - 1;
    return index - 1;
}
inline int get_next(int index, int dir){
    if (dir == 1)
        return left(index);
    return right(index);
}
inline void fill(int start, int dir){
    int index = start, count = 1;
    int next = get_next(index, dir);
    v[start] = 0;
    while(b[index] <= b[next] && v[index] == 0){
        v[index] = count;
        if(b[index] < b[next])
            count += 1;
        else
            count = 1;
        index = next;
        next = get_next(index, dir);
    }
    v[start] = 1;
}
int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d", &n);
        v.clear();a.clear(); b.clear(); 
        for(int i = 0; i < n; ++i){
            scanf("%d", &x);
            v.push_back(0);
            b.push_back(x);
            a.push_back(make_pair(x, i));
        }
        sort(a.begin(), a.end());
        for(int i = 0; i < n; ++i){
            int index = a[i].second;
            if (v[index] != 0)
                continue;
            if (v[left(index)] != 0 && v[right(index)] != 0)
                v[index] = max(v[left(index)], v[right(index)]) + 1;
            if (v[left(index)] == 0)
                fill(index, 1);
            if (v[right(index)] == 0)
                fill(index, -1);
        }
        long long answer = 0;
        for(int i = 0; i < n; ++i){
            answer += v[i];
        }
        printf("%lld\n", answer);
    }
    return 0;
} 
第四题,被数据量吓到了,但是这个数据量,肯定要二分长度,简单算下N*log(L)应该是可以过,所以二分最大长度,朴素的check是否满足就可以了
思路:能否等分出m个长度为L的绳子,在l ∈ [0, L] 上是个不减问题,即如果某个满足此条件的最大位置为l,则大于l的无法等分,小于l的可以等分
因此,二分满足题意的L,找到最大位置判断即可,复杂度已经算过是OK的,注意停止条件和输出位数有关;以及边界问题(r减 l不增,因为k是满足的)
代码,怕python不过,直接c++了:
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
using namespace std;
int n, m, x;
vector<double> a;
inline bool check(double l){
    int count = 0;
    for(int i = n - 1; i >= 0 && a[i] >= l; --i){
        count += floor(a[i] / l);
    }
    return count >= m;
}
inline double solve(int m){
    double l = 0.f, r = a[n-1] + 1.f;
    while( r - l > 1e-3){
        double k = (l + r) / 2;
        if (check(k))
            l = k;
        else
            r = k - 0.001;
    }
    return l;
}
int main(){
    scanf("%d%d", &n, &m);
    for(int i = 0; i < n; ++i){
        scanf("%d", &x);
        a.push_back((double)x);
    }
    sort(a.begin(), a.end());
    printf("%.2lf", solve(m));
    return 0;
}
第三题卡了被Python好久,总以为复杂度算错了T_T
以上。祝大家都能拿到满意offer,许愿~


#字节跳动##春招##笔试题目##题解##笔经##算法工程师#
全部评论
感觉今年A三道多才能进面试~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
点赞 回复 分享
发布于 2019-03-16 12:34
半小时切完124,然后发消息求考官解释了一下第3题样例,拓扑排序过。。。点交卷的时候刚好一个小时= = 今年真的是简单了,去年的题我感觉都是非常规的思维题,看了几题表示有点自闭。。。
点赞 回复 分享
发布于 2019-03-16 12:38
膜拜大佬
点赞 回复 分享
发布于 2019-03-16 12:17
啊,第二题的空白怎么也去不掉,就这样吧,下午要去面试了,晚上回复。没有offer,心里慌慌
点赞 回复 分享
发布于 2019-03-16 12:22
大佬,第四题我用Java在循环中用了in.nextInt(),为什么提交报错
点赞 回复 分享
发布于 2019-03-16 12:24
为啥我投的测开和你的题目是一样的啊。我以为会是和去年一个套路。结果都是编程题啊!
点赞 回复 分享
发布于 2019-03-16 12:27
woc,牛逼
点赞 回复 分享
发布于 2019-03-16 12:35
菜鸟想问一下头条春招还会不会像秋招一样有几次笔试机会😂
点赞 回复 分享
发布于 2019-03-16 12:37
大神 膜
点赞 回复 分享
发布于 2019-03-16 12:38
第三题没做出来,考试结束后有了一个想法: 先扫描一遍:     分数比左右都小的人(极小值)派1个礼物。如4 3 4,中间得3分的人派1个礼物     分数非严格单调递增的人,派1个礼物。如5 5 6,中间得5分的人派1个礼物     分数严格单调递增的,比隔壁多1个礼物。如4 5 6,中间的人比得4分的人多1个礼物     分数单调递减的,如5 4 4和5 4 3,先不管。     分数比左右都大的(极大值),如4 5 4,先不管 再反方向扫描一遍     注意此时是从右向左看增减性了     分数从右到左严格单调递增的人,比右边的人多派1个礼物,如 6 5 4,则5分的人比4分的人多1个礼物     分数从右到左非严格单调递增的人,派1个礼物,如 6 5 5,则中间5分的人派1个礼物     分数比左右都大的人,派max(左边的礼物,右边的礼物)+1个礼物
点赞 回复 分享
发布于 2019-03-16 12:50
点赞 回复 分享
发布于 2019-03-16 12:53
//Dalao厉害,第四题完全没想到用二分; //我考试时写的第三题O(n),想法可能简单点 #include <iostream> #include <vector> #include <algorithm> #include <utility> using namespace std; int main() {     int n;     cin >> n;     for (int i = 0; i < n; ++i) {         int people;         cin >> people;         vector<int> point(people, 0);         vector<long long> pres(people, 1);         vector<pair<int, int> > mark(people, make_pair(0, 0));         for (int j = 0; j < people; ++j) cin >> point[j];         if (people == 0) {             cout << 0 << endl;             continue;         }         if (people == 1) {             cout << 1 << endl;             continue;         }         if (people == 2) {             if (point[0] == point[1]) cout << 2 << endl;             else cout << 3 << endl;             continue;         }         for (int j = 0; j < people; ++j) {                 int left = j - 1 < 0 ? people - 1 : j - 1;                 int right = (j + 1) % people;                 if (point[j] > point[left]) mark[j].first = 1;                 if (point[j] > point[right]) mark[j].second = 1;         }         for (int j = 0; j < people; ++j) {             if (mark[j].first == 0 && mark[j].second == 0) {                 int left = j - 1 < 0 ? people - 1 : j - 1;                 while (mark[left].second == 1) {                     pres[left] = max(pres[left], pres[(left+1)%people] + 1);                     left = left - 1 < 0 ? people - 1 : left - 1;                 }                 int right= (j + 1) % people;                 while (mark[right].first == 1) {                     pres[right] = max(pres[right], pres[right-1<0?people-1:right-1] + 1);                     right = (right + 1) % people;                 }             }         }         long long result = 0;         for (int j = 0; j < people; ++j) result += pres[j];         cout << result << endl;     }     return 0; }
点赞 回复 分享
发布于 2019-03-16 13:29
今年的题简单,一个小时基本上就做完了,秋招把我恶心到了。1题动态规划,2题栈,3题和LeetCode135基本一样,4题我也是使用二分
点赞 回复 分享
发布于 2019-03-16 13:30
骚啊。还有二分查找答案这种操作。这是把题目当作NP来做。
点赞 回复 分享
发布于 2019-03-16 13:40
大佬,请问第四题,r=a[n-1]+1.f,为什么要加1呀
点赞 回复 分享
发布于 2019-03-16 16:15
第一题我一直过不去,然后用位运算也没过,菜是原罪😂
点赞 回复 分享
发布于 2019-03-16 19:16
第四题其实是可以直接百度到的
点赞 回复 分享
发布于 2019-03-17 08:52
有大神 知道原题在哪里可以找到?
点赞 回复 分享
发布于 2019-03-17 19:05
感谢大佬提供解题思路
点赞 回复 分享
发布于 2019-03-19 12:26
第三题 python 同11%,换c++ ac 哈哈,握手😄
点赞 回复 分享
发布于 2019-03-19 13:24

相关推荐

点赞 评论 收藏
分享
点赞 112 评论
分享
牛客网
牛客企业服务