Skip to content
Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
class Solution {
public:
int matrixMedian(vector<vector<int>>& grid)
{
int m = grid.size();
int n = grid[0].size();
int k = (m*n+1)/2;

int left = 0, right = INT_MAX;
while (left < right)
{
int mid = left+(right-left)/2;
int count = 0;
for (int i=0; i<m; i++)
count += upper_bound(grid[i].begin(), grid[i].end(), mid) - grid[i].begin();
if (count < k)
left = mid + 1;
else
right = mid;
}

return left;

}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
### 2387.Median-of-a-Row-Wise-Sorted-Matrix

令`k=(m*n+1)/2`,本题就是求矩阵里的从小到大的第k个元素。本质和`215.Kth-Largest-Element-in-an-Array`相同,只不过需要将各行`smallerOrEqual(mid)`的结果累加起来得到count。
```cpp
if (count < k)
left = mid+1;
else
right = mid;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using LL = long long;
class Solution {
LL dp[100005][2];
public:
vector<long long> minimumCosts(vector<int>& regular, vector<int>& express, int expressCost)
{
int n = regular.size();
regular.insert(regular.begin(), 0);
express.insert(express.begin(), 0);

dp[0][0] = 0;
dp[0][1] = expressCost;

vector<LL>rets;

for (int i=1; i<=n; i++)
{
dp[i][0] = min(dp[i-1][0] + regular[i], dp[i-1][1] + regular[i]);
dp[i][1] = min(dp[i-1][1] + express[i], dp[i-1][0] + expressCost + express[i]);

rets.push_back(min(dp[i][0], dp[i][1]));
}

return rets;
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
### 2361.Minimum-Costs-Using-the-Train-Line

很明显,状态变量dp[i][0]表示到达第i个车站的regular所需要的最小代价,dp[i][1]表示到达第i个车站的express所需要的最小代价。于是有转移方程:
```cpp
dp[i][0] = min(dp[i-1][0] + regular[i], dp[i-1][1] + regular[i]);
dp[i][1] = min(dp[i-1][1] + express[i], dp[i-1][0] + expressCost + express[i]);
```
注意我们不需要考虑dp[i][0]与dp[i][1]之间的转移。这是因为,我们如果想要从dp[i][0]转移到dp[i][1],其目的一定只是为了后续得到dp[i+1][1]。单独从第i站的角度来看,只要到了regular或express都算达成了任务,两者间的跳转对于第i站而言没有意义。
4 changes: 4 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
[159.Longest-Substring-with-At-Most-Two-Distinct-Characters](https://github.com/wisdompeak/LeetCode/tree/master/Two_Pointers/159.Longest-Substring-with-At-Most-Two-Distinct-Characters)(H-)
[340.Longest-Substring-with-At-Most-K-Distinct-Characters](https://github.com/wisdompeak/LeetCode/tree/master/Two_Pointers/340.Longest-Substring-with-At-Most-K-Distinct-Characters) (H)
[992.Subarrays-with-K-Different-Integers](https://github.com/wisdompeak/LeetCode/tree/master/Two_Pointers/992.Subarrays-with-K-Different-Integers) (H-)
[2461.Maximum-Sum-of-Distinct-Subarrays-With-Length-K](https://github.com/wisdompeak/LeetCode/tree/master/Two_Pointers/2461.Maximum-Sum-of-Distinct-Subarrays-With-Length-K) (M)
* ``Two pointers for two seuqences``
[986.Interval-List-Intersections](https://github.com/wisdompeak/LeetCode/tree/master/Two_Pointers/986.Interval-List-Intersections) (M)
[1229.Meeting-Scheduler](https://github.com/wisdompeak/LeetCode/tree/master/Two_Pointers/1229.Meeting-Scheduler) (M+)
Expand Down Expand Up @@ -128,6 +129,7 @@
[793.Preimage-Size-of-Factorial-Zeroes-Function](https://github.com/wisdompeak/LeetCode/tree/master/Binary_Search/793.Preimage-Size-of-Factorial-Zeroes-Function) (H-)
[1201.Ugly-Number-III](https://github.com/wisdompeak/LeetCode/tree/master/Binary_Search/1201.Ugly-Number-III) (H-)
[1539.Kth-Missing-Positive-Number](https://github.com/wisdompeak/LeetCode/tree/master/Binary_Search/1539.Kth-Missing-Positive-Number) (H-)
[2387.Median-of-a-Row-Wise-Sorted-Matrix](https://github.com/wisdompeak/LeetCode/tree/master/Binary_Search/2387.Median-of-a-Row-Wise-Sorted-Matrix) (H-)

#### [Hash Map](https://github.com/wisdompeak/LeetCode/tree/master/Hash)
[049.Group-Anagrams](https://github.com/wisdompeak/LeetCode/tree/master/Hash/049.Group-Anagrams) (M+)
Expand Down Expand Up @@ -678,6 +680,7 @@
[2036.Maximum-Alternating-Subarray-Sum](https://github.com/wisdompeak/LeetCode/tree/master/Dynamic_Programming/2036.Maximum-Alternating-Subarray-Sum) (M+)
[2143.Choose-Numbers-From-Two-Arrays-in-Range](https://github.com/wisdompeak/LeetCode/tree/master/Dynamic_Programming/2143.Choose-Numbers-From-Two-Arrays-in-Range) (H)
[2318.Number-of-Distinct-Roll-Sequences](https://github.com/wisdompeak/LeetCode/tree/master/Dynamic_Programming/2318.Number-of-Distinct-Roll-Sequences) (H-)
[2361.Minimum-Costs-Using-the-Train-Line](https://github.com/wisdompeak/LeetCode/tree/master/Dynamic_Programming/2361.Minimum-Costs-Using-the-Train-Line) (M+)
* ``基本型 II``
[368.Largest-Divisible-Subset](https://github.com/wisdompeak/LeetCode/tree/master/Dynamic_Programming/368.Largest-Divisible-Subset) (M+)
[300.Longest-Increasing-Subsequence](https://github.com/wisdompeak/LeetCode/tree/master/Greedy/300.Longest-Increasing-Subsequence) (M+)
Expand Down Expand Up @@ -952,6 +955,7 @@
[133.Clone-Graph](https://github.com/wisdompeak/LeetCode/tree/master/Recursion/133.Clone-Graph) (M+)
[213.House-Robber-II](https://github.com/wisdompeak/LeetCode/tree/master/Dynamic_Programming/213.House-Robber-II) (H-)
[337.House-Robber-III](https://github.com/wisdompeak/LeetCode/tree/master/Recursion/337.House-Robber-III) (M+)
[2378.Choose-Edges-to-Maximize-Score-in-a-Tree](https://github.com/wisdompeak/LeetCode/tree/master/Recursion/2378.Choose-Edges-to-Maximize-Score-in-a-Tree) (H-)
[390.Elimination-Game](https://github.com/wisdompeak/LeetCode/tree/master/Recursion/390.Elimination-Game) (H)
[395.Longest-Substring-with-At-Least-K-Repeating-Characters](https://github.com/wisdompeak/LeetCode/tree/master/Recursion/395.Longest-Substring-with-At-Least-K-Repeating-Characters) (H)
[397.Integer-Replacement](https://github.com/wisdompeak/LeetCode/tree/master/Recursion/397.Integer-Replacement) (M+)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using LL = long long;
class Solution {
vector<pair<int,LL>>children[100005];
LL memo[100005][2];
public:
long long maxScore(vector<vector<int>>& edges)
{
int n = edges.size();
int root = -1;
for (int i=0; i<n; i++)
{
if (edges[i][0]==-1)
{
root = i;
continue;
}
int par = edges[i][0];
int weight = edges[i][1];
children[par].push_back({i, weight});
}

return dfs(root, 0);
}

LL dfs(int node, int status)
{
if (memo[node][status]!=0)
return memo[node][status];

if (status == 0)
{
LL sum = 0;
for (auto& [child, weight]: children[node])
sum += dfs(child, 0);

LL maxSum = sum;
for (auto& [child, weight]: children[node])
maxSum = max(maxSum, sum - dfs(child, 0) + dfs(child, 1) + weight);

memo[node][0] = maxSum;
return maxSum;
}
else
{
LL sum = 0;
for (auto& [child, weight]: children[node])
sum += dfs(child, 0);
memo[node][1] = sum;
return sum;
}
}
};
11 changes: 11 additions & 0 deletions Recursion/2378.Choose-Edges-to-Maximize-Score-in-a-Tree/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
### 2378.Choose-Edges-to-Maximize-Score-in-a-Tree

我们不难发现,如果从parent到node的edge被选中的话,那么node到它所有children的edge都不能选中。如果从parent到node的edge不被选中的话,那么node到它所有children的edge里只能最多选一条。

所以我们定义`dfs(node, 1)`表示从parent到node的edge被选中,那么以node为根的子树的最大收益。于是有
```cpp
dfs(node, 1) = sum{dfs(child, 0)};
```
同理,定义`dfs(node, 0)`表示从parent到node的edge不被选中,那么以node为根的子树的最大收益。因为我们允许有一条node的子边被选中,所以需要遍历这个选择。为了便于计算,我们先求出`Sum = sum{dfs(child, 0)}`,那么对于任何一个child,如果它的边被选中的话,则整棵树的最大收益就是`Sum - dfs(child, 0) + dfs(child, 1) + weight`. 我们遍历child,再返回最大的作为`dfs(node,1)`.

显然,此题需要记忆化来避免重复计算。
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using LL = long long;
class Solution {
public:
long long maximumSubarraySum(vector<int>& nums, int k)
{
LL ret = 0;
unordered_map<int,int>Map;
int count = 0;
LL sum = 0;
for (int i=0; i<nums.size(); i++)
{
Map[nums[i]]++;
if (Map[nums[i]]==1)
count++;
sum += nums[i];

if (i>=k-1)
{
if (count == k)
ret = max(ret, sum);

Map[nums[i-k+1]]--;
sum -= nums[i-k+1];
if (Map[nums[i-k+1]]==0)
count--;
}
}

return ret;
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
### 2461.Maximum-Sum-of-Distinct-Subarrays-With-Length-K

非常普通的固定长度的滑窗。

用一个HashMap来记录每个number出现的次数。用count来表示滑窗内的distinct number的数量。count的变动依据如下:
1. 当新加入一个数字时
```cpp
Map[num]++;
if (Map[num]==1)
count++;
```
2. 当移出一个数字时
```cpp
Map[num]--;
if (Map[num]==0)
count--;
```