2015年部分網際網路公司筆試綜合題及答案
筆試了幾場,對部分題目做了下整理與總結,程式碼寫得比較渣,需要多多訓練。
網易演算法工程師崗程式設計題
- 問題描述:
小V今年有n門課,每門都課都有考試。為了拿到獎學金,小V必須讓自己的平均年成績至少為avg,每門課的最終成績由平時成績和考試成績組成,滿分為r,現在他知道每門課的平時成績為ai,如果想要讓自己這門課的成績多拿一分的話,小V必須花bi小時複習,不花時間意味著這門課的考試成績只能拿0分,平時成績加考試成績超過r這麼課最終成績也只能按r計算。為了拿到獎學金,請問小V至少需要花多少時間複習功課? 輸入:
輸入兩行資料,第一行是兩個整數:路燈數目n(1<=n<=1000),街道長度(1<=l<=pow(10, 9))。第二行有n個整數ai(0<=ai<=l),表示路燈座標,多個路燈可以在同一個地方,也可以安放在終止點位置。
樣例輸入:
5 5 4
5 2
4 7
3 1
3 2
2 5
結果:
4
Hint:
花兩個小時複習第三門考試拿兩分,兩個小時複習第四門考試拿一分,這樣總平均成績為(5+4+5+4+2)/4 = 4
解題思路:對第i門課程,如果要增加1分,需要花費bi個小時的時間,為了耗費的時間最小,我們肯定應該選那些增加1分所用時間短的課程複習。
程式碼步驟:先以bi(也就是以樣例中的時間列)為排序基準,對由ai和bi組成的矩陣(二維陣列)由小到大排序,然後逐步由花費時間最小的課程開始(也就是排序後的第一行)逐步增加1分,判斷總分數是否到了avg*n,到了就停止,否則繼續加1分。
下面是自己寫的參考程式碼,沒考慮輸入邊界情況,寫得比較渣,思路比較好理解。
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
using namespace std;
int main(int argc, const char * argv[]) {
int n, r, avg;
cin >> n >> r >> avg;
vector<int> A(n);
vector<int> B(n);
for(int i = 0; i < n; i++){
int tmpAi, tmpBi;
cin >> tmpAi >> tmpBi;
A[i] = tmpAi;
B[i] = tmpBi;
}
vector<size_t> indexes(n);
size_t nn(0);
generate(begin(indexes), end(indexes), [&]{return nn++;});
sort(begin(indexes), end(indexes), [&](int i1, int i2){return B[i1] < B[i2];});
vector<int> sortedA(n);
vector<int> sortedB(n);
for(int i = 0; i < n; i++){
sortedB[i] = B[indexes[i]];
sortedA[i] = A[indexes[i]];
}
int sum = accumulate(sortedA.begin(), sortedA.end(), 0);
int time = 0;
int i = 0;
while((sum < avg*n) && (i < n)){
int addScores = 0;
while((sortedA[i] + addScores) < 5 && sum < avg*n){
sum = sum + 1;
time = time + sortedB[i];
++addScores;
}
++i;
}
cout << time << endl;
return 0;
}
- 問題描述:
V先生有一天工作得很晚,回家的時候要穿過一條長度為l的筆直街道,這條街道上有n個路燈。假設這條街起點為0,終點為l,第i個路燈的座標為ai。路燈發光能力以正數d來衡量,其中d表示路燈能夠照亮的街道上的點與路燈的最遠距離,所有路燈發光能力相同。為了讓V先生看清回家的路,路燈必須照亮整天街道,又為了節省電力希望找到最小的d是多少?
輸入:
輸入兩行資料,第一行是兩個整數:路燈數目n(1<=n<=1000),街道長度(1<=l<=pow(10, 9))。第二行有n個整數ai(0<=ai<=l),表示路燈座標,多個路燈可以在同一個地方,也可以安放在終止點位置。
樣例輸入:
7 15
15 5 3 7 9 14 0
結果:
2.5
解題思路:找出相鄰座標差值中最大的,然後除以2便是最小的d。
程式碼步驟:先進行輸入處理,將其儲存在looc
中,再對其進行由小到大的排序,然後計算找出相鄰座標中最大的差值。
下面是自己寫的參考程式碼,沒考慮輸入邊界情況,寫得比較渣,思路比較好理解。
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, const char * argv[]) {
int numBulb, distance;
cin >> numBulb >> distance;
vector<int> looc(numBulb);
for(int i = 0; i < numBulb; i++){
int tmp;
cin >> tmp;
looc[i] = tmp;
}
sort(looc.begin(), looc.end(), less<int>());
int maxDis = 0;
for(int i = 0; i < numBulb; i++){
int tmp = looc[i+1]-looc[i];
if(tmp > maxDis)
maxDis = tmp;
}
cout << maxDis/2.0 << endl;
return 0;
}
大眾點評資料探勘崗綜合題
上面這道題跟第二天考的大眾點評資料探勘崗綜合題的第二題解題思路一樣,該題題目為:
N個為排序的整數,線上性時間內,求這N個數在數軸上相鄰兩個數之間的最大差值(寫出關鍵演算法)
順便吐槽一下,大眾點評Java考得真多,綜合題的第一題要求用Java用遞迴實現階乘計算,虐得真慘,找完工作了Java搞起。
另外大眾點評綜合題第三題是貝葉斯公式的運用,題目描述如下:
某公司有兩個部門,A部門有30名女生和24名男生,B部分有12名女生和42名男生。現在從兩個部門中挑選出一個女生來安排一次聯誼團建,請問這個女生來自A部門的概率為多少?
解:
- 設H1表示A部門,H2表示B部門,P(H1) = P(H2) = 0.5, P(E|H1) = 30/54, P(E|H2) = 12/54;
- 設E表示女生,則問題轉成求P(H1|E);
- P(E) = P(E|H1)P(H1) + P(E|H2)P(H2) = 7/18;
- 根據條件概率公式有:
- P(H1|E) = P(H1)P(E|H1)/P(E) = 0.5(30/54)/(7/18) = 0.714
京東演算法崗綜合題
- 問題描述:
輸入資料僅包含一組測試樣例,對於每組測試案例,共有兩行輸入資料,輸入第一行代表要處理的字串s1(不超過50),輸入第二行代表替換的字串s2(不超過10).
樣例輸入:
You are the best
123
To be NO.1
Yes
Thank you very much
%%%
樣例輸出:
You1234are1234the1234best
ToYesbeYesNO.1
Thank%%%you%%%very%%%much
解題思路:可以參閱《劍指offer》P46頁替換空格那道題。
#include <iostream>
using namespace std;
char* replace_blank(char str[], char strB[], int len, int lenB)
{
if(str == NULL || len <= 0) {
return NULL;
}
int i = 0, numberBlanks = 0; // cnt為整個字串的空格個數,size為字串字元個數
while(str[i] != '\0') {
if(str[i] == ' ') {
++numberBlanks;
}
++i;
}
for(i = len-1; i >= 0; --i) {
if(str[i] != ' ') {
str[i+numberBlanks*(lenB - 1)] = str[i];
// 測試輸出
//char tt = str[i];
//int tmp = i+numberBlanks*(lenB - 1);
//cout << tmp << ": " << tt << endl;
}
else {
for(int j = 0; j < lenB; j++){
str[i+numberBlanks*(lenB - 1) - j] = strB[lenB -1 - j];
// 測試輸出
//char tt = strB[lenB -1 - j];
//int tmp = i+numberBlanks*(lenB - 1) - j;
//cout << tmp << ": " << tt << endl;
}
--numberBlanks;
}
}
return str;
}
int main(int argc, const char * argv[]) {
string inputA, inputB;
getline(cin, inputA);
getline(cin, inputB);
int lenA = (int)inputA.length();
int lenB = (int)inputB.length();
char strA[lenA];
char insertedB[lenB];
strcpy(strA, inputA.c_str());
strcpy(insertedB, inputB.c_str());
char* afterInserted = replace_blank(strA, insertedB, lenA, lenB);
cout << afterInserted << endl;
return 0;
}
- 問題描述:
小東和三個小朋友在一起玩小球,他們是一種新玩法。他們站在樓房的不同層,假設小東站在的樓層距離地面N米,球從小東的手裡自由落下,每次落地後跳回返回原地面的一半;再落回地下,再反跳回原高度的一半。小東和三個小朋友站在不同的樓層,同時放下手中不同的小球,當小球全部落下地面不跳事,求4個小球一共經過了多少米?(數字都為整數)。
輸入:
輸入4個數字,分別表示四個小球距離地面的高度,所有輸入的數字都為整數,範圍不能超過整數所能表示的最大值。
輸出:
輸出為4個小球經過的總長度
樣例輸入:
100 90 80 70
樣例輸出:
996
解題思路:這道題只要不是等比數列取極限定勢思維先入為主,並且注意到了數字都為整數這條資訊,就非常非常容易做了,當時做的時候真坑,沒注意到數字都為整數,然後陷入等比數列取極限的坑。下面是自己寫的參考程式碼:
int ballDistance(int h){ int sumH = h; int halfH = (int)h/2.0; while(halfH != 0){ sumH = sumH + 2*halfH; halfH = (int)halfH/2.0; } return sumH; } int main(int argc, const char * argv[]) { int t1, t2, t3, t4; cin >> t1 >> t2 >> t3 >> t4; int sum = ballDistance(t1) + ballDistance(t2) + ballDistance(t3) + ballDistance(t4); cout << sum << endl; return 0; }
from: http://yongyuan.name/blog/written-examination-of-some-companys.html