目錄
- 一、檸檬水找零-LeetCode 860
- 思路
- 實現代碼
- 個人問題
- 總結
- 二、根據身高重建隊列-LeetCode 406
- 思路
- 實現代碼
- 個人問題
- 總結
- 三.用最少數量的箭引爆氣球-LeeCode 406
- 思路
- 實現代碼
- 個人問題
- 總結
一、檸檬水找零-LeetCode 860
Leecode鏈接: leetcode 860
文章鏈接: 代碼隨想錄
視頻鏈接: B站
在檸檬水攤上,每一杯檸檬水的售價為 5 美元。顧客排隊購買你的產品,(按賬單 bills 支付的順序)一次購買一杯。
每位顧客只買一杯檸檬水,然后向你付 5 美元、10 美元或 20 美元。你必須給每個顧客正確找零,也就是說凈交易是每位顧客向你支付 5 美元。
注意,一開始你手頭沒有任何零錢。
給你一個整數數組 bills ,其中 bills[i] 是第 i 位顧客付的賬。如果你能給每位顧客正確找零,返回 true ,否則返回 false 。
示例:
輸入:bills = [5,5,5,10,20]
輸出:true
解釋:
前 3 位顧客那里,我們按順序收取 3 張 5 美元的鈔票。
第 4 位顧客那里,我們收取一張 10 美元的鈔票,并返還 5 美元。
第 5 位顧客那里,我們找還一張 10 美元的鈔票和一張 5 美元的鈔票。
由于所有客戶都得到了正確的找零,所以我們輸出 true。
思路
對數組的元素進行計數,如果是5就加1,如果是10,就判斷5的個數是否大于0,大于0就將5的個數減一并將10的個數加一否則就返回false。如果是20,就判斷5的個數是否大于3或者有1個5跟一個10,否則返回false。
實現代碼
//cpp
class Solution {
public:bool lemonadeChange(vector<int>& bills) {int count5 = 0;int count10 = 0;for(int i = 0;i<bills.size();i++){if(bills[i] == 5){count5++;}else if(bills[i] == 10){if(count5 <= 0){return false;}count10 ++;count5 --;}else{if(count5>0&&count10>0){count5 --;count10--;}else if(count5>=3){count5 -= 3;}else {return false;}}}return true;}
};
個人問題
無。
總結
整體比較簡單。
二、根據身高重建隊列-LeetCode 406
Leecode鏈接: LeetCode 406
文章鏈接: 代碼隨想錄
視頻鏈接: B站
假設有打亂順序的一群人站成一個隊列,數組 people 表示隊列中一些人的屬性(不一定按順序)。每個 people[i] = [hi, ki] 表示第 i 個人的身高為 hi ,前面 正好 有 ki 個身高大于或等于 hi 的人。
請你重新構造并返回輸入數組 people 所表示的隊列。返回的隊列應該格式化為數組 queue ,其中 queue[j] = [hj, kj] 是隊列中第 j 個人的屬性(queue[0] 是排在隊列前面的人)。
示例:
輸入:people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]
輸出:[[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]
解釋:
編號為 0 的人身高為 5 ,沒有身高更高或者相同的人排在他前面。
編號為 1 的人身高為 7 ,沒有身高更高或者相同的人排在他前面。
編號為 2 的人身高為 5 ,有 2 個身高更高或者相同的人排在他前面,即編號為 0 和 1 的人。
編號為 3 的人身高為 6 ,有 1 個身高更高或者相同的人排在他前面,即編號為 1 的人。
編號為 4 的人身高為 4 ,有 4 個身高更高或者相同的人排在他前面,即編號為 0、1、2、3 的人。
編號為 5 的人身高為 7 ,有 1 個身高更高或者相同的人排在他前面,即編號為 1 的人。
因此 [[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]] 是重新構造后的隊列。
思路
題目首先對數組的首個元素按照從大到小排序,如果相同,則按照第二個元素從小到大排序。排完序后再根據第二個元素從小到大進行排序。至于理由可以這么考慮,第一次排完序后,最后面的首個元素肯定是最小的,這也就意味著它可以直接根據它自身的第二個元素挑選要插入的位置,反正他前面都是比他大的,需要插的位置直接按照第二個元素來就行。
實現代碼
//cpp
class Solution {
public:static bool cmp(const vector<int>&a,const vector<int>&b){if(a[0] == b[0]){return a[1]<b[1];}return a[0]>b[0];}vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {list<vector<int>> que;sort(people.begin(),people.end(),cmp);for(int i = 0;i<people.size();i++){int p = people[i][1];std::list<vector<int>>::iterator it = que.begin();// while(p--){// it++;// }advance(it,p);que.insert(it,people[i]);}return vector<vector<int>>(que.begin(),que.end());}
};
個人問題
沒有想到怎么做。
總結
題目思路很巧妙,還是需要進行兩次的排序,屬于想不到就做不出來。
三.用最少數量的箭引爆氣球-LeeCode 406
Leecode鏈接: LeetCode 406
文章鏈接: 代碼隨想錄
視頻鏈接: B站
有一些球形氣球貼在一堵用 XY 平面表示的墻面上。墻面上的氣球記錄在整數數組 points ,其中points[i] = [xstart, xend] 表示水平直徑在 xstart 和 xend之間的氣球。你不知道氣球的確切 y 坐標。
一支弓箭可以沿著 x 軸從不同點 完全垂直 地射出。在坐標 x 處射出一支箭,若有一個氣球的直徑的開始和結束坐標為 xstart,xend, 且滿足 xstart ≤ x ≤ xend,則該氣球會被 引爆 。可以射出的弓箭的數量 沒有限制 。 弓箭一旦被射出之后,可以無限地前進。
給你一個數組 points ,返回引爆所有氣球所必須射出的 最小 弓箭數 。
示例:
輸入:points = [[10,16],[2,8],[1,6],[7,12]]
輸出:2
解釋:氣球可以用2支箭來爆破:
-在x = 6處射出箭,擊破氣球[2,8]和[1,6]。
-在x = 11處發射箭,擊破氣球[10,16]和[7,12]。
思路
初始設置res為1,因為第一個氣球一定需要一枚箭。i初始值為1,循環檢查第i個氣球跟第i-1個氣球是否重合,重合了就將第i個氣球的右坐標更新為第i-1個氣球的右坐標,沒有重合就將res自加1,并開始下一個循環。
實現代碼
//cpp
class Solution {
private:static bool cmp(const vector<int>& a, const vector<int>& b) {return a[0] < b[0];}
public:int findMinArrowShots(vector<vector<int>>& points) {if (points.size() == 0) return 0;sort(points.begin(), points.end(), cmp);int result = 1; // points 不為空至少需要一支箭for (int i = 1; i < points.size(); i++) {if (points[i][0] > points[i - 1][1]) { // 氣球i和氣球i-1不挨著,注意這里不是>=result++; // 需要一支箭}else { // 氣球i和氣球i-1挨著points[i][1] = min(points[i - 1][1], points[i][1]); // 更新重疊氣球最小右邊界}}return result;}
};
個人問題
思路有但是代碼沒寫出來。
總結
思路有但是卡在了如何保存上一個重疊氣球的坐標值上,解決辦法是如果重合了,就保存在本次循環i表示的右坐標上,因為下次對比所對比的就是上一次循環的右節點的右坐標是否大于本次循環的左坐標。