力扣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]: - 移出 1 和 4 ,之後 nums = [2,3] - 移出 2 和 3 ,之後 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 解釋:二進位制下,1,2 和 3 分別對應 "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]; } };