# Weekly Contest 392
日期:2024/04/07
這是第二次做 LeetCode weekly contest,很可惜卡在第三題沒完全做完。
此次題目:
- [Longest Strictly Increasing or Strictly Decreasing Subarray](https://leetcode.com/problems/longest-strictly-increasing-or-strictly-decreasing-subarray/)
- [Lexicographically Smallest String After Operations With Constraint](https://leetcode.com/problems/lexicographically-smallest-string-after-operations-with-constraint/)
- [Minimum Operations to Make Median of Array Equal to K](https://leetcode.com/problems/minimum-operations-to-make-median-of-array-equal-to-k/)
- [Minimum Cost Walk in Weighted Graph](https://leetcode.com/problems/minimum-cost-walk-in-weighted-graph/)
#### 第一題
使用兩個變數 `cur_inc` 與 `cur_dec` 計算最長遞增與遞減子陣列即可
```clike
class Solution {
public:
int longestMonotonicSubarray(vector<int>& nums) {
const int n = nums.size();
int ret = 1;
int cur_inc = 1;
int cur_dec = 1;
for(int i = 1; i < n; i++) {
if(nums[i] > nums[i - 1]) {
cur_inc++;
cur_dec = 1;
}else if(nums[i] < nums[i - 1]) {
cur_dec++;
cur_inc = 1;
}else {
cur_dec = 1;
cur_inc = 1;
}
ret = max(ret, cur_inc);
ret = max(ret, cur_dec);
}
return ret;
}
};
```
#### 第二題
題目可以轉化成:
1. 實作出距離的計算方式
2. 因為是 Lexicographically Smaller,可以從起始的字母開始處理,最小值是 `'a'`
```clike
class Solution {
public:
int calDis(char a, char b) {
int x = a - 'a';
int y = b - 'a';
int r1 = ((x - y) + 26) % 26;
int r2 = (26 - r1) % 26;
return min(r1, r2);
}
string getSmallestString(string s, int k) {
const int n = s.size();
for(int i = 0; i < n; i++) {
if(k <= 0)
break;
int d = calDis(s[i], 'a');
if(d <= k) {
s[i] = 'a';
k -= d;
}else{
if('a' + k < s[i])
s[i] = s[i] - k;
else
s[i] = 'a' + k;
k = 0;
}
}
return s;
}
};
```
#### 第三題
題目本身沒有解釋清楚中位數是哪個位置的數字,是 `nums[n / 2]` 的數字必須等於`k`
第一版本的程式碼有點寫錯,還包含幾個 edge cases 沒想到,例如
`nums = [1], k = 1000000000` 跟 `nums = [1000000000], k = 1`
它的思路是將大於、小於與等於 `k` 的分組,使用 `check` 函式確認中位數是否位於中間。
```clike
class Solution {
public:
long long minOperationsToMakeMedianK(vector<int>& nums, int k) {
// less than k
priority_queue<int> ll;
// greater than k
priority_queue<int, vector<int>, greater<int>> gg;
// equal to k
int ee = 0;
for(int x : nums) {
if(x > k)
gg.push(x);
else if(x < k)
ll.push(x);
else
ee++;
}
auto check = [&gg, &ll, &ee, &nums] {
const int mi = nums.size() / 2 + 1;
bool c1 = ll.size() + 1 == mi;
bool c2 = ee != 0 && ll.size() < mi && ll.size() + ee >= mi;
return c1 || c2;
};
long long ret = 0;
const int mi = nums.size() / 2 + 1;
while(!check()) {
int x;
if(ll.size() >= mi) {
x = ll.top();
ll.pop();
}else{
x = gg.top();
gg.pop();
}
int diff = abs(k - x);
ret += diff;
ee++;
}
return ret;
}
};
```
從[討論區](https://leetcode.com/problems/minimum-operations-to-make-median-of-array-equal-to-k/solutions/4985548/java-c-python-sort/)取得的解答,與上面的程式碼思路一模一樣,當下沒想出來:
```clike
class Solution {
public:
long long minOperationsToMakeMedianK(vector<int>& nums, int k) {
using ll = long long;
ll ret = 0;
const int n = nums.size();
sort(nums.begin(), nums.end());
for(int i = 0; i <= n / 2; i++)
ret += max(0, nums[i] - k);
for(int i = n / 2; i < n; i++)
ret += max(0, k - nums[i]);
return ret;
}
};
```