字节跳动 2019 春季算法实习生在线笔试

1. 题目一

求最少收到多少硬币,即优先用大面额的硬币找零,类似于求一个数的个位十位百位。

#include <iostream>
#include <stdio.h>

using namespace std;

int main()
{
    int n;
    scanf("%d", &n);

    int change = 1024 - n;
    int a = change / 64;
    int b = (change - a * 64) / 16;
    int c = (change - a * 64 - b * 16) / 4;
    int d = (change - a * 64 - b * 16 - c * 4) / 1;

    cout << a+b+c+d;
    return 0;
}

2. 题目二

先处理有连续三个字母的情况。遍历字符串,定义一个 cnt 变量,如果字符与前一个字符相同,则 cnt 增 1;若不同,cnt 置 1,继续向后遍历。若 cnt 增到 3,则当前字母应该被去除,cnt 减 1。

再处理 AABB 的情况,思路同上。遍历字符串,定义一个 cnt 变量,如果字符与前一个字符相同,则 cnt 增 1;若不同,cnt 置 1,继续向后遍历。若 cnt 增到 2,则直接查看其后的两个字符是否相同,若相同,去除第二个 B。

由于我们是从左向右遍历,所以第三种情况完全不用额外再处理。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>

using namespace std;
void Three_Consecutive(string &s);
void Remove_AABB(string &s);
int main()
{
    int n;
    scanf("%d", &n);

    vector<string> data(n);

    for (int i = 0; i < n; i++)
    {
        cin >> data[i];
    }

    for (int i = 0; i < n; i++)
    {
        Three_Consecutive(data[i]);
        Remove_AABB(data[i]);
        cout << data[i] << endl;
    }

    return 0;
}

void Remove_AABB(string &s)
{
    int n = s.size();
    string temp;
    int same = s[0];
    int cnt = 1;
    temp.push_back(s[0]);
    for (int i = 1; i < n; i++)
    {
        int AABB_flag = 0;
        if (s[i] == same)
        {
            cnt++;
            if (cnt == 2) // 遇到两个连续的字符 AA,查看其后是否有 BB
            {
                if (i + 2 < n && s[i+1] == s[i+2])
                {
                    AABB_flag = 1;
                    cnt = 1;
                    same = s[i+1];
                }
            }
        }
        else
        {
            cnt = 1;
            same = s[i];
        }
        temp.push_back(s[i]);
        if (AABB_flag)
        {
            temp.push_back(s[i+1]);
            i = i + 2; // 跳过 BB 两个字符
        }
    }
    s = temp;
}

void Three_Consecutive(string &s)
{
    int n = s.size();
    string temp;
    int same = s[0];
    int cnt = 1;
    temp.push_back(s[0]);
    for (int i = 1; i < n; i++)
    {
        int flag = 0;
        if (s[i] == same)
        {
            cnt++;
            if (cnt == 3)
            {
                cnt--;
                flag = 1;
            }
        }
        else
        {
            cnt = 1;
            same = s[i];
        }
        if (!flag)  temp.push_back(s[i]);
    }
    s = temp;
}

3. 题目三

此题与 LeetCode 135——分发糖果 类似,只不过所有的人排成了一圈。因此,我们只需要先找到得分最小的人,然后以此为起始点分别向左向右遍历求得左右序奖赏即可。

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>

using namespace std;

int Cal_Reward(vector<int> &data)
{
    int min_value = data[0];
    int min_index = 0;
    int n = data.size();
    for (int i = 1; i < n; i++)
    {
        if (data[i] < min_value)
        {
            min_value = data[i];
            min_index = i;
        }
    }

    vector<int> left_reward(n, 1);
    for (int i = min_index + 1; i != min_index; i++)
    {
        int left = i - 1;
        int right = i;

        if (i == n)
        {
            right = 0;
            i = 0;
            left = n - 1;
        }

        if (data[right] > data[left])    left_reward[right] = left_reward[left] + 1;
        if (min_index == i)   break; // 最小值为 data[0]
    }

    vector<int> right_reward(n, 1);
    for (int i = min_index - 1; i != min_index; i--)
    {
        int left = i;
        int right = i + 1;

        if (i == -1)
        {
            right = 0;
            i = n - 1;
            left = i;
        }

        if (data[left] > data[right])    right_reward[left] = right_reward[right] + 1;
        if (min_index == i)   break; // 最小值为 data[n-1]
    }

    int result = 0;
    for (int i = 0; i < n; i++)
    {
        result += max(right_reward[i], left_reward[i]);
    }
    return result;
}

int main()
{
    int n;
    scanf("%d", &n);

    for (int i = 0; i < n; i++)
    {
        int num;
        scanf("%d", &num);
        vector<int> data(num, 0);
        for (int j = 0; j < num; j++)
        {
            cin >> data[j];
        }

        cout << Cal_Reward(data) << endl;
    }

    return 0;
}

4. 题目四

此题与 今日头条 2018 AI Camp 5 月 26 日在线笔试编程题第二道——最小分割分数 相似。绳子的长度最短为 0,最长为 N 根绳子的最大值。因此采用二分搜索,如果某个长度的值可以裁剪出 M 根绳子,继续往右搜索,否则向左搜索,直到区间小于 1e-3 结束。

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>

using namespace std;

int main()
{
    int n = 0, m = 0;
    scanf("%d %d", &n, &m);

    vector<int> data(n, 0);
    int max_length = 0;
    for (int i = 0; i < n; i++)
    {
        cin >> data[i];
        max_length = max_length > data[i] ? max_length : data[i];
    }

    float left = 0;
    float right = max_length;

    float result;
    while (fabs(right - left) >= 1e-3)
    {
        float mid = left + (right - left) / 2;

        int num = 0;
        for (int i = 0; i < n; i++)
        {
            num += int(data[i] / mid);
        }

        if (num >= m)
        {
            left = mid;
            result = mid;
        }
        else
        {
            right = mid;
        }
    }

    printf("%.2f", result);

    return 0;
}

获取更多精彩,请关注「seniusen」!

posted @ 2019-03-23 20:42  seniusen  阅读(1443)  评论(0编辑  收藏  举报