字節跳動 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」!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM