1. 程式人生 > 實用技巧 >力扣218場周賽

力扣218場周賽

1.**設計 Goal 解析器**

請你設計一個可以解釋字串 command 的 Goal 解析器 。command 由 "G"、"()" 和/或 "(al)" 按某種順序組成。Goal 解析器會將 "G" 解釋為字串 "G"、"()" 解釋為字串 "o" ,"(al)" 解釋為字串 "al" 。然後,按原順序將經解釋得到的字串連線成一個字串。

給你字串 command ,返回 Goal 解析器 對 command 的解釋結果。

示例1:
輸入:command = "G()(al)"
輸出:"Goal"
解釋:Goal 解析器解釋命令的步驟如下所示:
G -> G
() -> o
(al) 
-> al 最後連線得到的結果是 "Goal" 示例2: 輸入:command = "G()()()()(al)" 輸出:"Gooooal" 示例3: 輸入:command = "(al)G(al)()()G" 輸出:"alGalooG"
class Solution {
public:
    string interpret(string command) {
        string res;
        for(int i=0;i<command.size();i++){
            if(command[i]=='G') res+="G";
            
else{ if(command[i+1]==')'){ res+="o"; i++; } else{ res+="al"; i+=3; } } } return res; } };

2.K 和數對的最大數目
給你一個整數陣列 nums 和一個整數 k 。
每一步操作中,你需要從陣列中選出和為 k 的兩個整數,並將它們移出陣列。
返回你可以對陣列執行的最大運算元。

示例1:
輸入:nums = [1,2,3,4], k = 5
輸出:2
解釋:開始時 nums = [1,2,3,4]:
- 移出 14 ,之後 nums = [2,3]
- 移出 23 ,之後 nums = []
不再有和為 5 的數對,因此最多執行 2 次操作。

示例2:
輸入:nums = [3,1,3,4,3], k = 6
輸出:1
解釋:開始時 nums = [3,1,3,4,3]:
移出前兩個 3 ,之後nums = [1,4,3]
不再有和為 6 的數對,因此最多執行 1 次操作。

提示:
  1 <= nums.length <= 105
  1 <= nums[i] <= 109
  1 <= k <= 109
class Solution {
public:
    int maxOperations(vector<int>& nums, int k) {
        sort(nums.begin(),nums.end());
        int res=0;
        int i=0,j=nums.size()-1;
        while(i<j){
            if(nums[i]+nums[j]==k){
                res++;
                i++;
                j--;
            }
            else if(nums[i]+nums[j]<k){
                i++;
            }
            else    j--;
        }
        return res;
    }

3.連線連續二進位制數字
給你一個整數 n ,請你將 1 到 n 的二進位制表示連線起來,並返回連線結果對應的 十進位制 數字對 1e9 + 7 取餘的結果。

示例1:
輸入:n = 1
輸出:1
解釋:二進位制的 "1" 對應著十進位制的 1 。

示例2:
輸入:n = 3
輸出:27
解釋:二進位制下,123 分別對應 "1""10""11" 。
將它們依次連線,我們得到 "11011" ,對應著十進位制的 27 。

示例3:
輸入:n = 12
輸出:505379714
解釋:連線結果為 "1101110010111011110001001101010111100" 。
對應的十進位制數字為 118505380540 。
對 1e9 + 7 取餘後,結果為 505379714 。

提示:
- 1 <= n <= 1e5

這道題其實可以簡單理解為這樣:假設N=3,那麼最後應該輸出的結果是11011,如果n=2,那麼結果應該是110,如果n=1,那就結果就是1.
不難發現如果我們要計算3,那麼我們從1開始計算,1和2的連線中,1向左移動了2位,那麼我們可以直接1<<2+2;這樣就可以成功把1和2的二進位制連線起來了。接下來連線3,3的二進位制是11,有兩位,說明我們上一步計算的將結果要左移兩位再加上3.
最後可以總結出我們所需的結果是上一次結果<<這一次需要加上的數字的二進位制位數+這次計算的數字值。即tmp=tmp<<i的位數+i;

class Solution {
public:
    int concatenatedBinary(int n) {
        int res=0;
        long long int tmp=0;
        for(int i=1;i<=n;i++){
            int move=0;    //統計需要移動的位數
            int cns=i;
            while(cns){
                move++;
                cns/=2;
            }
            tmp=tmp<<move;
            tmp+=i;
            tmp%=(int)(1E9+7);
        }
        return tmp;
    }
};

4.最小不相容性
給你一個整數陣列 nums​​​ 和一個整數 k 。你需要將這個陣列劃分到 k 個相同大小的子集中,使得同一個子集裡面沒有兩個相同的元素。
一個子集的 不相容性 是該子集裡面最大值和最小值的差。
請你返回將陣列分成 k 個子集後,各子集 不相容性 的 和 的 最小值 ,如果無法分成分成 k 個子集,返回 -1 。
子集的定義是陣列中一些數字的集合,對數字順序沒有要求。

示例1:
輸入:nums = [1,2,1,4], k = 2
輸出:4
解釋:最優的分配是 [1,2] 和 [1,4] 。
不相容性和為 (2-1) + (4-1) = 4 。
注意到 [1,1] 和 [2,4] 可以得到更小的和,但是第一個集合有 2 個相同的元素,所以不可行。

示例2:
輸入:nums = [6,3,8,1,3,1,2,2], k = 4
輸出:6
解釋:最優的子集分配為 [1,2],[2,3],[6,8] 和 [1,3] 。
不相容性和為 (2-1) + (3-2) + (8-6) + (3-1) = 6 。

示例3:
輸入:nums = [5,3,3,6,3,3], k = 3
輸出:-1
解釋:沒辦法將這些數字分配到 3 個子集且滿足每個子集裡沒有相同數字。

提示:
  1 <= k <= nums.length <= 16
  nums.length 能被 k 整除。
  1 <= nums[i] <= nums.length


下面程式碼是第一名大佬的程式碼,我沒有做出這道題目,暫時先複製下來他的程式碼,過一段時間再好好研究研究。

class Solution {
private:
    int freq[20];
public:
    int minimumIncompatibility(vector<int>& nums, int k) {
        int n = nums.size();
        vector<int> valid(1 << n, -1);
        for (int mask = 0; mask < (1 << n); ++mask) {
            if (__builtin_popcount(mask) == n / k) {
                for (int j = 0; j < n; ++j) {
                    if (mask & (1 << j)) {
                        ++freq[nums[j]];
                    }
                }
                bool flag = true;
                for (int j = 1; j <= n; ++j) {
                    if (freq[j] > 1) {
                        flag = false;
                        break;
                    }
                }
                if (flag) {
                    int lb = INT_MAX, rb = INT_MIN;
                    for (int j = 1; j <= n; ++j) {
                        if (freq[j] > 0) {
                            lb = min(lb, j);
                            rb = max(rb, j);
                        }
                    }
                    valid[mask] = rb - lb;
                }
                for (int j = 0; j < n; ++j) {
                    if (mask & (1 << j)) {
                        --freq[nums[j]];
                    }
                }
            }
        }
        
        vector<int> f(1 << n, -1);
        f[0] = 0;
        for (int mask = 1; mask < (1 << n); ++mask) {
            if (__builtin_popcount(mask) % (n / k) == 0) {
                for (int sub = mask; sub; sub = (sub - 1) & mask) {
                    if (valid[sub] != -1 && f[mask ^ sub] != -1) {
                        if (f[mask] == -1) {
                            f[mask] = f[mask ^ sub] + valid[sub];
                        }
                        else {
                            f[mask] = min(f[mask], f[mask ^ sub] + valid[sub]);
                        }
                    }
                }
            }
        }
            
        return f[(1 << n) - 1];
    }
};