###### tags: `Weekly Contest`
# Weekly Contest 336
## [2586. Count the Number of Vowel Strings in Range](https://leetcode.com/problems/count-the-number-of-vowel-strings-in-range/) (<font color=#00B8A3>Easy</font>)
### Solution
直接遍歷從 left 到 right 的所有字串,並檢查所有字串是否符合 vowel string 的特徵。
#### 時間複雜度: ***O(n)***
#### 空間複雜度: ***O(1)***
程式碼:
```c++=
class Solution {
public:
int vowelStrings(vector<string>& words, int left, int right) {
set<char> vowel = {'a', 'e', 'i', 'o', 'u'};
int ans = 0;
for(int i=left;i<=right;i++){
if(vowel.count(words[i][0]) && vowel.count(words[i].back()))
ans++;
}
return ans;
}
};
```
## [2587. Rearrange Array to Maximize Prefix Score](https://leetcode.com/problems/rearrange-array-to-maximize-prefix-score/) (<font color=#FFC011>Medium</font>)
### Solution
比較正負數的順序,發現**要使 prefix array 正數最多的話,在 nums 裡的非負數就必須放在負數的前面**。再來是**負數之間的排序,會希望負數越小的排在越前面**,這樣 prefix sum 的 decresing 會越慢。
綜合以上條件,只要將整個 nums 陣列由大排到小之後,計算 prefix sum 有幾個大於 0 即是答案。
#### 時間複雜度 ***O(n * logn)***
#### 空間複雜度 ***O(n)***
程式碼:
```c++=
class Solution {
public:
int maxScore(vector<int>& nums) {
sort(nums.begin(), nums.end(), greater<int>()); // 將nums陣列從大排到小
vector<long long> prefix={0};
for(int i=0;i<nums.size();i++) // 產生 prefix array
prefix.push_back(prefix.back()+nums[i]);
int ans = 0;
for(int i=1;i<prefix.size();i++){
if(prefix[i]>0)
ans++;
else break;
}
return ans;
}
};
```
### Optimized solution
同樣的想法,但在空間上可以只用一個 prefix 變數,而不需要建構整個 prefix array。
#### 時間複雜度 : ***O(n * logn)***
#### 空間複雜度 : ***O(1)***
程式碼:
```c++=
class Solution {
public:
int maxScore(vector<int>& nums) {
sort(nums.begin(), nums.end(), greater<int>());
long long prefix = 0, ans = 0;
for(int i=0;i<nums.size();i++, ans++){
prefix+=nums[i];
if(prefix<=0)
break;
}
return ans;
}
};
```
## [2588. Count the Number of Beautiful Subarrays](https://leetcode.com/problems/count-the-number-of-beautiful-subarrays/) (<font color=#FFC011>Medium</font>)
### Solution
#### Observation 1
將 beautiful array 的每個元素的每個bit是 1 的數量統計出來。
> 以範例測資 \[4,3,1,2,4] 來舉例
> 100 4
> 011 3
> 001 1
> 010 2
> 100 4
> \-------
> 222
根據 beautiful array 的定義,beautiful array 的每個 bit 1的數量必是偶數。
而將一個 array 所有元素 xor,如果值等於 0,該陣列就是 beautiful array。
#### Observation 2
直接窮舉所有 subarray 的時間複雜度是 ***O(n^2)***,所以需要一個更快速的方法來計算,不然會 TLE。
這時候可以使用類似 prefix sum 的概念,只是這次需要計算的不是 sum 而是 xor。
> arr 1 2 3 4 5
> prefix sum 0 1 3 6 10 15
> prefix\[i] = nums\[0] xor nums\[1] ... xor nums\[i]
nums\[i] xor nums\[i+1] ... xor nums\[j] = prefix\[i-1] xor prefix\[j]
#### 時間複雜度 : ***O(n)***
#### 空間複雜度 : ***O(n)***
程式碼:
```c++=
class Solution {
public:
long long beautifulSubarrays(vector<int>& nums) {
int prefix = 0;
map<int, long long> mp;
mp[0]++;
cout<<prefix<<' ';
for(int i=0;i<nums.size();i++){
prefix = prefix ^ nums[i];
cout<<prefix<<" ";
mp[prefix]++;
}
cout<<"\n";
long long ans = 0;
for(auto &it: mp){
ans += it.second*(it.second-1)/2;
}
return ans;
}
};
```
## [2589. Minimum Time to Complete All Tasks](https://leetcode.com/problems/minimum-time-to-complete-all-tasks/description/) (<font color=#FF375F>Hard</font>)
### Solution(參考[這篇](https://leetcode.com/problems/minimum-time-to-complete-all-tasks/solutions/3286311/intuition-explained-video-solution-just-sort-greedy-c-java/?orderBy=most_votes))
#### Observation
對於整個排序好的區間來說,將電腦運行的時間盡可能的往後推是最好的,這樣可以使更多的區間可能被覆蓋,進而讓整體開機時間 minimize。
解題演算法
1. 先將 tasks 照結束時間由小到大排好。
2. 遍歷所有 tasks,假設當下task的區間有 t 時間被使用過,如果有的話就將該 task 所需時間減去 t。
3. 接著盡可能的將電腦使用的時間往後推遲,並同時記錄使用了多長的時間。
4. 最終紀錄的時間即是答案
#### 時間複雜度: ***O(n^2)***
#### 空間複雜度: ***O(n)***
程式碼:
```c++=
class Solution {
#define MAX 2005
public:
static bool cmp(vector<int> &a, vector<int> &b){
if(a[1] !=b[1])
return a[1] < b[1];
else return a[0] < b[0];
}
int findMinimumTime(vector<vector<int>>& tasks) {
sort(tasks.begin(), tasks.end(), cmp);
bool isUsed[MAX] = {0};
int ans = 0;
for(auto &t: tasks){
int useTime = 0;
for(int i=t[0];i<=t[1];i++){
if(isUsed[i])
useTime++;
}
for(int i=t[1];useTime<t[2];i--){
if(!isUsed[i]){
isUsed[i] = true;
ans++;
useTime++;
}
}
}
return ans;
}
};
```