字节跳动 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」!