騰訊筆試題--微信紅包
本來這題沒什麼難度,不值得我寫部落格的,誰知道一個失誤花了半小時才做出來。寫下來告誡自己不要再犯錯。
春節期間小明使用微信收到很多個紅包,非常開心。在檢視領取紅包記錄時發現,某個紅包金額出現的次數超過了紅包總數的一半。請幫小明找到該紅包金額。寫出具體演算法思路和程式碼實現,要求演算法儘可能高效。
給定一個紅包的金額陣列gifts及它的大小n,請返回所求紅包的金額。
若沒有金額超過總數的一半,返回0。測試樣例:
[1,2,3,2,2],5
返回:2
其實就是求超過陣列一半的元素問題,劍指offer上有。
方法一:利用partition方法
class Gift {
public:
int getValue(vector<int> gifts, int n) {
if(n <= 0)
return -1;
int start = 0;
int end = n - 1;
int middle = (end - start) >> 1;
int index = -1;
index = partition(gifts, start, end);
while(index < middle){
if(index > middle){ //index>middle,說明中位數在左邊,我們需要左調整end
end = index - 1;
index = partition(gifts, start, end);
}
else{ //index <= middle,說明中位數在右邊,需要右調整start
start = index + 1;
index = partition(gifts, start, end);
}
}
return check_more_than_half(gifts, n, gifts[middle]);
}
int partition(vector<int> gifts, int start, int end){
int small = start - 1; //在這行和下面這行,我想把我自己叫哥了,經常由於寫程式碼寫的快把start寫成0,因為這個耽擱時間我真是醉了...
for(int index=start; index<end; ++index){
if(gifts[index] < gifts[end]){
++small;
if(index != small)
std::swap(gifts[index], gifts[small]);
}
}
++small;
std::swap(gifts[small], gifts[end]);
return small;
}
int check_more_than_half(vector<int>& gifts, const int n, int val){
int cnt = 0;
for(auto i : gifts){
if(i == val)
++cnt;
}
return (cnt != 0 && cnt > (n >> 1)) ? val : 0;
}
};
基於陣列的partition方法是成熟的用來求第k位數的方法,在此處我們用來求的是中位數。我們求得中位數,然後判斷中位數是否超過陣列的一半就得出答案了。
如果求第k個數,while迴圈條件改為index< k-1(或Index != k-1)即可。
對於每次partition得出的index,如果index>middle,說明中位數在index左邊(當前index所對的元素肯定大於中位數)。否則,中位數在index右邊。當index=middle時,成功求得中位數,會跳出迴圈。
這個方法的時間複雜度是O(N)。
另外,千萬注意partition中是start,不是0。
方法二:攻守陣地法
我們把第一個元素作為士兵,並使用一個計數變數times。遍歷陣列,如果出現相同元素,times++。如果出現不同元素,times–。當times減為0時,該士兵死亡。使用新的gifts[i]作為士兵,繼續攻守。最後留在戰場上的士兵有可能就是超過一半的數字。
最後利用check函式判斷即可。
程式碼如下:
class Gift {
public:
int getValue(vector<int> gifts, int n) {
if(n <= 0)
return -1;
int times = 1;
int soldier = gifts[0];
for(int i=1; i<n; ++i){
if(soldier == gifts[i])
++times;
else if(soldier != gifts[i]){
if(--times == 0){
soldier = gifts[i];
times = 1;
}
}
}
return check_more_than_half(gifts, n, soldier);
}
int check_more_than_half(vector<int>& gifts, const int n, const int val){
int cnt = 0;
for(auto i : gifts){
if(i == val)
++cnt;
}
return (cnt != 0 && cnt > (n >> 1)) ? val : 0;
}
};
該方法時間複雜度同樣是O(N)。
相關文章
- 騰訊筆試題筆試
- 騰訊筆試題集筆試
- 微信紅包的概率測試程式
- 騰訊往屆筆試面試題整理大全筆試面試題
- 騰訊9.6筆試筆試
- 騰訊PHP實習生筆試題目及答案解析PHP筆試
- 微信紅包介面呼叫(rails)AI
- 騰訊研發類筆試面試試題及答案(C++方向)筆試面試C++
- 微信LazyMan筆試題的深入解析和實現筆試
- 微信商戶 API 發紅包!API
- 微信紅包體系設計分析
- 高仿微信搶紅包動畫特效動畫特效
- 2017騰訊Web前端實習生招聘筆試題總結Web前端筆試
- 騰訊社招筆面試題面試題
- 如何做微信紅包封面專案?
- 微信公眾號下發紅包 -- PHPPHP
- 微信小程式搶紅包實現效果微信小程式
- 筆試題目——研發工程師筆試題筆試工程師
- Python教你全自動搶微信紅包Python
- 微信搶紅包遊戲繞過指定尾數遊戲
- 微信紅包火了,釣魚網站樂了網站
- java筆試題Java筆試
- shell 筆試題筆試
- SQL 筆試題SQL筆試
- 2019騰訊實習筆試題部分記錄+兩次電話面試筆記筆試面試筆記
- 測試筆試多選題筆試
- 軟體測試筆試題筆試
- 模擬微信搶紅包demo,生成隨機數隨機
- 微信小程式搶紅包高併發設計微信小程式
- Android微信新版全自動搶紅包助手Android
- 基於Auto.js的微信紅包監測JS
- 微信搶紅包遊戲繞過指定尾數(2)遊戲
- php筆試題gtalentPHP筆試
- IT公司筆試題(四)筆試
- c++筆試題C++筆試
- SXF科技筆試題筆試
- linux筆試題Linux筆試
- DBA筆試題(轉)筆試