1. 程式人生 > 其它 >leetcode-第45場雙週賽

leetcode-第45場雙週賽

技術標籤:Leetcode周賽演算法leetcodealgorithm

題目A:

5657. 唯一元素的和

題目描述:

給你一個整數陣列 nums 。陣列中唯一元素是那些只出現 恰好一次 的元素。

請你返回 nums 中唯一元素的 和 。

示例 1

輸入:nums = [1,2,3,2]

輸出:4

解釋:唯一元素為 [1,3] ,和為 4 。

解題思路:

模擬。

使用hash表記錄每個元素的出現的次數,然後通過一次遍歷取得所有出現一次的所有元素的sum。

解題程式碼:

class Solution {
public:
int sumOfUnique(vector<int>& nums) {
unordered_map<int, int> hash;
for (auto x : nums) hash[x] ++;
int res = 0;
for (auto [k, v] : hash)
if (v == 1)
res += k;
return res;
}
};

題目B:

5658. 任意子陣列和的絕對值的最大值

題目描述:

給你一個整數陣列nums。一個子陣列[numsl, numsl+1, ..., numsr-1, numsr]的 和的絕對值為abs(numsl + numsl+1 + ... + numsr-1 + numsr)。

請你找出 nums中 和的絕對值 最大的任意子陣列(可能為空),並返回該 最大值。

abs(x)定義如下:

如果x是負整數,那麼abs(x) = -x。

如果x是非負整數,那麼abs(x) = x。

示例 1

輸入:nums = [1,-3,2,3,-4]

輸出:5

解釋:子陣列 [2,3] 和的絕對值最大,為 abs(2+3) = abs(5) = 5 。

解題思路:

字首和。

整體思路:

根據字首和陣列能夠快速求取區間和,而絕對值的最大值無非是找到這個區間和中的最大值和最小值,做一次遍歷,求取差值的最大情況即可。一般絕對值需要利用區間的最大和最小值兩種情況來分析替代。

第1步:求陣列的字首和陣列sum

第2步: 遍歷字首和陣列,每次擷取與區間最小值的差值,以及與區間最大值的差值。維護這兩個差值中的較大值。

第3步:返回區間差值最大值。

解題程式碼:

class Solution {
public:
int maxAbsoluteSum(vector<int>& nums) {
int n = nums.size();
vector<int> s(n + 1);
for (int i = 1; i <= n; i ++ ) s[i] = s[i - 1] + nums[i - 1];
int res = 0;
int minv = 0, maxv = 0;
for (int i = 1; i <= n; i ++ ) {
res = max(res, abs(s[i] - minv));
res = max(res, abs(s[i] - maxv));
minv = min(minv, s[i]);
maxv = max(maxv, s[i]);
}
return res;
}
};

題目C:

5659. 刪除字串兩端相同字元後的最短長度

題目描述:

給你一個只包含字元 'a','b'和 'c'的字串s,你可以執行下面這個操作(5 個步驟)任意次:

選擇字串 s一個 非空 的字首,這個字首的所有字元都相同。

選擇字串 s一個 非空 的字尾,這個字尾的所有字元都相同。

字首和字尾在字串中任意位置都不能有交集。

字首和字尾包含的所有字元都要相同。

同時刪除字首和字尾。

請你返回對字串 s執行上面操作任意次以後(可能 0 次),能得到的 最短長度。

示例1

輸入:s = "ca"

輸出:2

解釋:你沒法刪除任何一個字元,所以字串長度仍然保持不變。

解題思路:

貪心,模擬,雙指標。

指標p從前掃描,指標q從後掃描,將前後相同字元的部分刪掉。

需要特判的情況,當最後只剩下一個字元是是不能繼續刪除的,因為前後待刪區間是不能存在交集的。

只需要一遍的掃描,時間複雜度是O(n)。

解題程式碼:

class Solution {
public:
int minimumLength(string s) {
int i = 0, j = s.size() - 1;
while (i < j) {
if (s[i] != s[j]) break;
char c = s[i];
while (i <= j && s[i] == c) i ++ ;
while (i <= j && s[j] == c) j -- ;
}
return j - i + 1;
}
};

題目D:

5660. 最多可以參加的會議數目 II

題目描述:

給你一個events陣列,其中events[i] = [startDayi, endDayi, valuei],表示第i個會議在startDayi天開始,第endDayi天結束,如果你參加這個會議,你能得到價值valuei。同時給你一個整數k表示你能參加的最多會議數目。

你同一時間只能參加一個會議。如果你選擇參加某個會議,那麼你必須 完整地參加完這個會議。會議結束日期是包含在會議內的,也就是說你不能同時參加一個開始日期與另一個結束日期相同的兩個會議。

請你返回能得到的會議價值最大和。

示例 1

輸入:events = [[1,2,4],[3,4,3],[2,3,1]], k = 2

輸出:7

解釋:選擇綠色的活動會議 0 和 1,得到總價值和為 4 + 3 = 7 。

解題思路:
DP。
題目給出若干區間,每個區間有權值,從中選出若干區間且不想相交,使得權值最大。
解題步驟:
第1步:將所有的區間按右端點排序。
第2步:

解題程式碼:

const int N = 1000010;

struct Q {
int s, e, v;
bool operator< (const Q& t) const {
return e < t.e;
}
}q[N];
class Solution {
public:
int maxValue(vector<vector<int>>& events, int k) {
int n = events.size();
vector<vector<int>> f(n + 1, vector<int>(k + 1));
for (int i = 1; i <= n; i ++ )
q[i] = {events[i - 1][0], events[i - 1][1], events[i - 1][2]};
sort(q + 1, q + 1 + n);
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= k; j ++ ) {
f[i][j] = f[i - 1][j];
int l = 0, r = i - 1;
while (l < r) {
int mid = l + r + 1 >> 1;
if (q[mid].e < q[i].s) l = mid;
else r = mid - 1;
}
f[i][j] = max(f[i][j], f[r][j - 1] + q[i].v);
}
return f[n][k];
}
};