###### Agenda:
###### 10/12 10:00(UTC+8) 10/11 19:00(UTC-7)
###### 公布這次live session題目
###### 10/12 10:45(UTC+8) 10/11 19:45(UTC-7)
###### 開始逐步給hint
###### 10/12 11:30(UTC+8) 10/11 20:30(UTC-7)
###### 題解 + Q&A
###### 還沒有加入DC伺服器的請記得加入,並去查看#學員驗證頻道進行驗證才可以看到live session的討論區https://discord.gg/WUE3XutPK3
---
## 本周題目
## LeetCode biweekly contest 97
## https://leetcode.com/contest/biweekly-contest-97/
---
### Hint
- Q1 :
- hint 1: 想一想如何把一個數字每一位拿出來
----
### Hint
- Q1
- hint 1: 想一想如何把一個數字每一位拿出來
- hint 2: %10 可以拿到一個數字的個位數
----
### Hint
- Q1
- hint 1: 想一想如何把一個數字每一位拿出來
- hint 2: %10 可以拿到一個數字的個位數
- hint 3: /10 可以把數字十位數變個位數
---
### Hint
- Q2:
- hint 1: n不大所以可以每一個數字掃過去
----
### Hint
- Q2:
- hint 1: n不大所以可以每一個數字掃過去
- hint 2: 如何高效率的判斷一個數字存不存在於banned
----
### Hint
- Q2:
- hint 1: n不大所以可以每一個數字掃過去
- hint 2: 如何高效率的判斷一個數字存不存在於banned
- hint 3: 在總和大小被限制的情況下,希望取得數字盡量多,一定希望先取小的
---
### Hint
- Q3
- hint 1: 兩個segment不要重疊會比較好
----
### Hint
- Q3
- hint 1: 兩個segment不要重疊會比較好
- hint 2: segment的頭或尾貼著一個prize會比較好
----
### Hint
- Q3
- hint 1: 兩個segment不要重疊會比較好
- hint 2: segment的頭或尾貼著一個prize會比較好
- hint 3: 可以統一讓prize貼在segment頭部,這樣只會有n種segment的可能性
----
### Hint
- Q3
- hint 1: 兩個segment不要重疊會比較好
- hint 2: segment的頭或尾貼著一個prize會比較好
- hint 3: 可以統一讓prize貼在segment頭部,這樣只會有n種segment的可能性
- hint 4: 假設固定了第一個segment的位子,如何決定第二個segment的位子
---
### Hint
- Q4
- hint 1: 每走一步,x+y都會增大1
----
### Hint
- Q4
- hint 1: 每走一步,x+y都會增大1
- hint 2: 若一個格子不能被起點走到,或是不能走到終點,把他標成0也不會影響答案
----
### Hint
- Q4
- hint 1: 每走一步,x+y都會增大1
- hint 2: 若一個格子不能被起點走到,或是不能走到終點,把他標成0也不會影響答案
- hint 3: 考慮將棋盤逆時鐘轉45度看看
----
### Hint
- Q4
- hint 1: 每走一步,x+y都會增大1
- hint 2: 若一個格子不能被起點走到,或是不能走到終點,把他標成0也不會影響答案
- hint 3: 考慮將棋盤逆時鐘轉45度看看
- hint 4: 旋轉45度後,grid由右往左被分成好幾層,會發現每次移動都會往右移動一層,思考一下每一層的點數對於答案的影響
---
### 題解
----
### Q1 題目
- 給一些數字,在十進位情況下,將他們每一位拆開來。
- [12,34] -> [1,2,3,4]
----
### Q1
- 考慮單一一個數字,%10可以取得個位數,/10可以將目前的個位數移掉,重複做到數字變成0就可以了。
- 記得上述方法取出來會是反的,要將他反轉。
----
### Q1 c++ code
```c++
vector<int> separateDigits(vector<int>& nums) {
vector<int> ans;
for(int num : nums) {
vector<int> tmp;
if(num == 0) {
tmp.push_back(0);
}
while(num){
tmp.push_back(num % 10);
num /= 10;
}
reverse(tmp.begin(), tmp.end());
for(int it : tmp){
ans.push_back(it);
}
}
return ans;
}
```
----
### Test case
- 一位數
- 兩位會以上
- 有一位數為 0
- 單一一個 0
----
### Q2 題目
- 有$n$個數字,從$1$到$n$
- banned裡面的數字不能取
- 取越多數字的情況下,總和小於等於maxSum
----
### Q2 題目
- 用HashTable 整理banned,這樣等下可以快速找到那些數字不能用。
- 一定先取最小的數字,所以直接用迴圈從1掃到n。
----
```c++
int maxCount(vector<int>& banned, int n, int maxSum) {
unordered_set<int> visit;
for(int num : banned) {
visit.insert(num);
}
int sum = 0;
int cnt = 0;
for(int i = 1 ; i <= n ; i++) {
if(visit.find(i) == visit.end() && sum + i <= maxSum) {
sum += i;
cnt++;
}
}
return cnt;
}
```
----
### Test case
- 所有數字取完都不會超過maxSum
- 所有數字取完會超過maxSum
- 1 被 ban 掉
----
### Q3 題目
- 在數線上,某些位子有一些寶藏,第i個寶藏在$x_i$這個位子
- 用兩個線段長度最大為k個線段去蓋住這些寶藏,使得蓋到的寶藏數量最多
----
### Q3
- 以每個寶藏的位子當作線段的最左邊,去計算該線段可以蓋到多少寶藏
- 可以用 sliding window 先做計算。
- 窮舉最左邊線段的位子,根據greedy的想法我們希望兩個線段不重疊會比較好,因此計算在當前窮舉的位子尾巴的後面可以蓋到最多的寶藏
- 也可以用 sliding window 從右往左掃
- 注意當一個線段可以蓋住所有寶藏
----
```c++
int maximizeWin(vector<int>& prizePositions, int k) {
vector<int> covered;
int r = 0, cnt = 0;
for (int prize : prizePositions) {
while (r != prizePositions.size() &&
prizePositions[r] - prize <= k) {
r++;
cnt++;
}
covered.push_back(cnt);
cnt--;
}
r = prizePositions.size();
int Max = 0, ans = 0;
for (int i = prizePositions.size() - 1; i >= 0; i--) {
while (prizePositions[r - 1] - prizePositions[i] > k) {
r--;
Max = max(Max, covered[r]);
}
ans = max(ans, Max + covered[i]);
}
return ans;
}
```
----
### Test case
- 一個線段可以蓋住所有寶藏
- Greedy會錯
- 直接選一個線段可以蓋住最多寶藏
- [1, 2, 5, 6, 7, 8, 9, 12, 13] k = 5
- 讓距離比較近的寶藏一起蓋住
- [1,4,5,8] k = 3
- 寶藏會剛好卡在線段的頭跟尾
- [1,3,4,6] k = 2
- 答案的線段會有一個蓋在剛好頭或剛好尾
- [1,2,3] k = 1
----
### Q4 題目
- 給一個 $m * n$ 的 grid,每一格為 $0$ 或 $1$
- 保證左上跟右下一定為 $1$
- 可以從最左上(0, 0)開始移動,每次只能移動往右或往下且只能到$1$的位子
- 判斷是否能將除了左上或右下外的其中一個 $1$ 改成 $0$,使得最左上走不到最右下
----
### Q4
- 根據hint 2,將不影響答案的格子先移掉
- 旋轉$45$度後,若除了頭尾外,存在一層的點數只剩下一個就是true,反之則為false。
- 假設最左邊是第0層,可以發現第$i$層的所有格子$(x,y)$,$x+y=i$
----
### 判斷起點能不能走到
```c++
for (int i = 0; i < vis.size(); i++) {
for (int j = 0; j < vis[0].size(); j++) {
if ((i != 0 || j != 0) && vis[i][j] == 1) {
if (i != 0 && vis[i - 1][j] == 1) {
vis[i][j] = 1;
} else if (j != 0 && vis[i][j - 1] == 1) {
vis[i][j] = 1;
} else {
vis[i][j] = 0;
}
}
}
}
```
----
### 判斷能不能走到終點
```
for (int i = vis2.size() - 1; i >= 0; i--) {
for (int j = vis2[0].size() - 1; j >= 0; j--) {
if ((i != vis2.size() - 1 || j != vis2[0].size() - 1) &&
vis2[i][j] == 1) {
if (i != vis2.size() - 1 && vis2[i + 1][j] == 1) {
vis2[i][j] = 1;
} else if (j != vis2[0].size() - 1 && vis2[i][j + 1] == 1) {
vis2[i][j] = 1;
} else {
vis2[i][j] = 0;
}
}
}
}
```
----
### 判斷答案
```
for (int i = 1; i < grid.size() + grid[0].size() - 2; i++) {
int cnt = 0;
for (int j = 0; j < grid.size(); j++) {
int x = j, y = i - j;
if (y >= 0 && y < grid[0].size()) {
if (vis[x][y] && vis2[x][y]) {
cnt++;
}
}
}
if (cnt <= 1)
return true;
}
return false;
```
----
### Test case
- 答案為 no
- 一開始就走不到
- 除了左上跟右下外都是 0
- n=1,m=1
- 在沒有做 hint2 的清除下,每一層都會有兩個以上的點
---
### 幫我們填寫一下回饋表單讓我們變得更好
- https://forms.gle/fgFqxJqTEdaZw1cDA
- 
{"title":"1012 live session","description":"Q1 :","contributors":"[{\"id\":\"214a576a-9d94-453a-a11d-248251d46d4e\",\"add\":10134,\"del\":3959,\"latestUpdatedAt\":1760239741175}]"}