---
# System prepended metadata

title: Weekly Contest 336
tags: [Weekly Contest]

---

###### 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;
    }
};
```
