【字节跳动】2019后端笔试题

早上10点的笔试,晕的要死,竟然没ak。。。都是因为第二题用了自己不熟悉的指针,一直找错。。

#include <iostream>
#include<cstring>
#include<cmath>
#include<string>
#include<map>
#include<algorithm>
#include<stdio.h>
using namespace std;
int n,m,c;
int x,y,z;
double  a[101001];
const double eps=1e-3;
struct node
{
    char val;
    node *next;
    node(char s):val(s),next(NULL){}
};
void work(node *s)
{
    int sum=0;
    node *s1=s;
    int flag=0;
    while(s->val){
       while(s->next!=NULL){
           if(s->next->next==NULL)break;
           if((s->val==s->next->val)&&(s->val==s->next->next->val)){
           s->next=s->next->next;
           }
            else break;
       }
       while(s->next!=NULL){
           if(s->next->next==NULL)break;
           if(s->next->next->next==NULL)break;
          if((s->val==s->next->val)&&(s->next->next->val==s->next->next->next->val)){
         s->next->next=s->next->next->next;
         }
         else break;
       }
        if(s->next!=NULL)s=s->next;
        else break;
    }
    while(s1->val){
        printf("%c",s1->val);
          if(s1->next!=NULL)s1=s1->next;
          else break;
    }
    printf("\n");
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        char ss[100000];
        scanf("%s",ss);
         node *p=new node('0');
         node *p1=p;
       for(int j=0;j<strlen(ss);j++){
            node *pp=new node(ss[j]);
            p->next=pp;
            p=p->next;
       }
       work(p1->next);
    }
    return 0;
}

 

偷个懒,直接转载别人的吧

作者:牛客975268537号
链接:https://www.nowcoder.com/discuss/163780
来源:牛客网
 

第一题,大水题,直接上代码:

1

2

3

4

5

n, answer = 1024-int(input()), 0

for coin in [64, 16, 4, 1]:

  answer += n // coin

n = n % coin

print(answer)

第二题,比较简单,题目的中的两个判断条件,都只跟前2-3位字符有关。

思路:逐个判断字符,根据两个条件判断是否可以加到结果字符串中

代码:

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

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

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++重写了一遍:

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

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

#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++了:

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

32

33

34

35

#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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值