愛奇藝2018秋季校招測試工程師(第一場、第二場、第三場)程式設計題彙總
做了下愛奇藝2018測試工程師的程式設計題,教開發工程師還是偏簡單,特意寫了個程式設計題合集。
題目連結:
第一場
第一題:
題目:
牛牛有一些排成一行的正方形。每個正方形已經被染成紅色或者綠色。牛牛現在可以選擇任意一個正方形然後用這兩種顏色的任意一種進行染色,這個正方形的顏色將會被覆蓋。牛牛的目標是在完成染色之後,每個紅色R都比每個綠色G距離最左側近。牛牛想知道他最少需要塗染幾個正方形。
如樣例所示:
s = RGRGR
我們塗染之後變成RRRGG
滿足要求了,塗染的個數為2
,沒有比這個更好的塗染方案。
解析:
列舉,列舉最終塗好色的狀態,然後和目前的情況比較,維護一個最小值就行了。利用字首和優化,時間複雜度
O 。(n)
程式碼:
#include <bits/stdc++.h>
using namespace std;
int main()
{
string str;
while (cin >> str) {
int n = str.size();
vector<int> R(n + 2, 0), G(R);
for (int i = 1; i <= n; i++)
G[i] = G[i - 1] + (str[i - 1] == 'G');
for (int i = n; i > 0; i--)
R[i] = R[i + 1] + (str[i - 1] == 'R');
int ans = n;
for (int i = 0; i <= n; i++)
ans = min(ans, G[i] + R[i + 1]);
cout << ans << endl;
}
return 0;
}
第二題:
題目:
牛牛有羊羊有了屬於他們自己的飛機。於是他們進行幾次連續的飛行。
f[i]
表示第i
次飛行所需的燃油的升數。飛行只能按照f陣列所描述的順序進行。起初飛機裡有
s
升燃油,為了正常飛行,每次飛行前飛機內燃油量應大於等於此處飛行所需要的燃油量。請幫助他們計算在不進行加油的情況下他們能進行的飛行次數。
解析:
模擬就好了,這裡我用了二分去查詢字首和。
程式碼:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
bool cmp(const int &a, const int &b)
{
return a <= b;
}
int main()
{
int n, s;
while (cin >> n >> s) {
vector<int> sum(n + 1, 0);
for (int i = 1, x; i <= n; ++i)
sum[i] = sum[i - 1] + (cin >> x, x);
cout << lower_bound(sum.begin(), sum.end(), s, cmp) - sum.begin() - 1<< endl;
}
return 0;
}
第三題:
題目:
牛牛手中有三根木棍,長度分別是
a,b,c
。牛牛可以把任一一根木棍長度削短,牛牛的目標是讓這三根木棍構成一個三角形,並且牛牛還希望這個三角形的周長越大越好。
解析:
排個序,用兩較小的邊之和大於第三邊這個性質就可以解決了。
程式碼:
#include <bits/stdc++.h>
using namespace std;
int main()
{
vector<int> arr(3);
while (cin >> arr[0] >> arr[1] >> arr[2]) {
sort(arr.begin(), arr.end());
cout << (arr[0] + arr[1] > arr[2] ? arr[0] + arr[1] + arr[2] : 2 * (arr[0] + arr[1]) - 1) << endl;
}
return 0;
}
第二場
第一題:
題目:
牛牛有一個長度為
n
的整數序列,牛牛想對這個序列進行重排為一個非嚴格升序序列。牛牛比較懶惰,他想移動儘量少的數就完成重排,請你幫他計算一下他最少需要移動多少個序列中的元素。(當一個元素不在它原來所在的位置,這個元素就是被移動了的)。
解析:
不要想複雜了,題幹中加粗的句子就是做法。
程式碼:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
vector<int> pre((cin >> n, n));
for (int i = 0; i < n; cin >> pre[i++]);
vector<int> now(pre);
sort(now.begin(), now.end());
int ans = 0;
for (int i = 0; i < n; i++)
ans += (pre[i] != now[i]);
cout << ans << endl;
return 0;
}
第二題:
題目:
牛牛參加了一場考試,考試包括
n
道判斷題,每做對一道題獲得1
分,牛牛考試前完全沒有準備,所以考試只能看緣分了,牛牛在考試中一共猜測了t
道題目的答案是”正確”,其他的牛牛猜為”錯誤”。考試結束後牛牛知道實際上n
道題中有a
個題目的答案應該是”正確”,但是牛牛不知道具體是哪些題目,牛牛希望你能幫助他計算可能獲得的最高的考試分數是多少。
解析:
牛牛猜測
t
道正確,n-t
道題錯誤;而實際上正確的題有a
道,不正確的有n-a
道,牛牛多麼希望它選正確的那些題實際上也是對的,它選錯的那些題實際上也是錯的,這樣它才能獲得最多的分數。因此答案就是min(t, a) + min(n - t, n - a)
。
程式碼:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n, t, a;
cin >> n >> t >> a;
cout << min(t, a) + min(n - t, n - a) << endl;
return 0;
}
第三題:
題目:
有一種有趣的字串價值計算方式:統計字串中每種字元出現的次數,然後求所有字元次數的平方和作為字串的價值
例如: 字串
"abacaba"
,裡面包括4
個'a'
,2
個'b'
,1
個'c'
,於是這個字串的價值為4 * 4 + 2 * 2 + 1 * 1 = 21
牛牛有一個字串
s
,並且允許你從s
中移除最多k
個字元,你的目標是讓得到的字串的價值最小。
解析:
每次刪除一個出現最多次數的那個字母肯定是最優的,但是這個刪除是動態的,也就是說你每次刪除了那個次數最多的字母,下次這個字母出現的次數可能並不是最多的了。所以每次刪除過後排個序繼續刪除就可以了,我用的是優先佇列,每次取出隊頭的元素使其減一,然後再插入優先佇列。
程式碼:
#include <bits/stdc++.h>
using namespace std;
int main()
{
string str;
int k;
cin >> str >> k;
map<char, int> mp;
for (auto c : str)
mp[c]++;
priority_queue<int> que;
for (auto ele : mp)
que.push(ele.second);
int ans = 0;
for (; k--; ) {
int top = que.top();
que.pop();
if (top >= 1)
que.push(top - 1);
}
while (!que.empty())
ans += que.top() * que.top(), que.pop();
cout << ans << endl;
return 0;
}
第三場
第一題:
題目:
牛牛的老師給出了一個區間的定義:對於
x <= y,[x, y]
表示x
到y
之間(包括x
和y
)的所有連續整數集合。例如[3,3] = {3}, [4,7] = {4,5,6,7}
.牛牛現在有一個長度為n
的遞增序列,牛牛想知道需要多少個區間並起來等於這個序列。例如:
{1,2,3,4,5,6,7,8,9,10}
最少只需要[1,10]
這一個區間;
{1,3,5,6,7}
最少只需要[1,1],[3,3],[5,7]
這三個區間。
解析:
看一下集合中連續兩個數是否在自然數上是連續的就可以了。
程式碼:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
while (cin >> n) {
vector<int> arr(n);
for (int i = 0; i < n; cin >> arr[i++]);
int ans = 1;
for (int i = 1; i < n; i++)
ans += (arr[i] != arr[i - 1] + 1);
cout << ans << endl;
}
return 0;
}
第二題:
題目:
牛牛有一個由小寫字母組成的字串
s
,在s
中可能有一些字母重複出現。比如在"banana"
中,字母'a'
和字母'n'
分別出現了三次和兩次。但是牛牛不喜歡重複。對於同一個字母,他只想保留第一次出現並刪除掉後面出現的字母。請幫助牛牛完成對
s
的操作。
解析:
用
set
維護一下這個字串中的字元,如果當前字元沒有在set
中,就輸出,然後加入到set
中;如果當前字元在set
中,就什麼都不做。
程式碼:
#include <bits/stdc++.h>
using namespace std;
int main()
{
string str;
while (cin >> str) {
set<char> st;
for (char c : str) {
if (st.end() == st.find(c)) {
cout << c;
st.insert(c);
}
}
cout << endl;
}
return 0;
}
第三題:
題目:
牛牛舉辦了一場數字遊戲,有
n
個玩家參加這個遊戲,遊戲開始每個玩家選定一個數,然後將這個數寫在紙上(十進位制數,無字首零),然後接下來對於每一個數字將其數位按照非遞減順序排列,得到新的數,新數的字首零將被忽略。得到最大數字的玩家贏得這個遊戲。
解析:
還是模擬,用
stringsteam
完成數字到字串、字串到數字的轉換就行了。只不過這個題的資料有點坑,必須寫成單組輸入才能過。
程式碼:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
stringstream sin;
cin >> n;
int ans = 0;
for (int i = 0; i < n; i++) {
string str;
cin >> str;
sort(str.begin(), str.end());
sin << str;
int tmp;
sin >> tmp;
sin.clear();
ans = max(ans, tmp);
}
cout << ans << endl;
return 0;
}