# 第三屆特雷維歡樂賽題解
[Q1](http://git.trevi.cc/RanceJen/trevi-competition/blob/master/20190614-3/Q1.md)
LeetCode 387. [First Unique Character in a String](https://leetcode.com/problems/first-unique-character-in-a-string/)
Time O(n) n = string size
Space O(k) k = 26
第一次把整個字串掃過,用一個 hash map 紀錄每個字母出現次數
接著從前面再往後掃一次,比對遇到的字母總出現次數,發現是 1 的話就回傳 index ,若是掃到底都沒有比對成功則回傳 -1
```=c++
int firstUniqChar(string s) {
map<char, int> recorder{};
for (const auto& v : s) {
recorder[v]++;
}
int i = 0;
for (; i < s.size(); ++i) {
if (recorder[s[i]] == 1) {
return i;
}
}
return -1;
}
```
---
[Q2](http://git.trevi.cc/RanceJen/trevi-competition/blob/master/20190614-3/Q2.md)
LeetCode 860. [Lemonade Change](https://leetcode.com/problems/lemonade-change/)
因為小的硬幣能組成大的,大的不能拆分成小的,所以找錢先用大的硬幣準沒錯。
用一個 map 紀錄現有各零錢數量,每次找零時先看大的能不能找,扣掉能找的部份,再看小的。把能找的都找完之後還有剩就代表沒得找了。
Time O(n) n = bills size
Space O(k) k = 3
```=c++
bool lemonadeChange(vector<int>& bills) {
map<int, int> coins{};
for (const auto& v : bills) {
coins[v]++;
auto less = v - 5;
if (less >= 20) {
auto need = min(less / 20, coins[20]);
coins[20] -= need;
less -= need * 20;
}
if (less >= 10) {
auto need = min(less / 10, coins[10]);
coins[10] -= need;
less -= need * 10;
}
if (less >= 5) {
auto need = min(less / 5, coins[5]);
coins[5] -= need;
less -= need * 5;
}
if (less != 0) {
return false;
}
}
return true;
}
```
---
[Q3](http://git.trevi.cc/RanceJen/trevi-competition/blob/master/20190614-3/Q3.md)
LeetCode 121. [Best Time to Buy and Sell Stock](https://leetcode.com/problems/best-time-to-buy-and-sell-stock/)
因為股票只能先買後賣,所以我們只需要看賣出前的最低點。
手上先拿好第一次的價格,開始一路往後看,每次都計算賣出的差額,紀錄最大差額,如果有當下價格比手上拿的還便宜的,就替換掉手上拿股票,因為這樣後續賣出差額會更大,然後繼續往後算下去。
Time O(n) n = prices size
Space O(1)
```=c++
int maxProfit(vector<int>& prices) {
if (prices.empty()) {
return 0;
}
int diff = 0;
int cur = prices[0];
for (const auto & v : prices) {
if (v < cur) {
cur = v;
}
else {
diff = max(diff, v - cur);
}
}
return diff;
}
```