Leetcode 第 403 场周赛题解
Leetcode 第 403 场周赛题解
题目1:3194. 最小元素和最大元素的最小平均值
思路
将数组 nums 排序后,利用双指针计算每一对 (minElement + maxElement) / 2,最小值即为答案。
代码
/*
* @lc app=leetcode.cn id=3194 lang=cpp
*
* [3194] 最小元素和最大元素的最小平均值
*/
// @lc code=start
class Solution
{
public:
double minimumAverage(vector<int> &nums)
{
int n = nums.size();
ranges::sort(nums);
double minAvg = INT_MAX;
for (int i = 0, j = n - 1; i < j; i++, j--)
minAvg = min(minAvg, (nums[i] + nums[j]) / 2.0);
return minAvg;
}
};
// @lc code=end
复杂度分析
时间复杂度:O(nlogn),其中 n 是数组 nums 的长度。
空间复杂度:O(1),忽略排序的开销。
题目2:3195. 包含所有 1 的最小矩形面积 I
思路
设最左、最右、最上、最下的 1 的行号/列号分别为 left、right、top、bottom,则答案为:(right - left + 1) * (bottom - top + 1)。
代码
/*
* @lc app=leetcode.cn id=3195 lang=cpp
*
* [3195] 包含所有 1 的最小矩形面积 I
*/
// @lc code=start
class Solution
{
public:
int minimumArea(vector<vector<int>> &grid)
{
int m = grid.size(), n = m ? grid[0].size() : 0;
int left = n, right = 0;
int top = m, bottom = 0;
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
{
if (grid[i][j] == 1)
{
left = min(left, i);
right = max(right, i);
top = min(top, j);
bottom = max(bottom, j);
}
}
return (right - left + 1) * (bottom - top + 1);
}
};
// @lc code=end
复杂度分析
时间复杂度:O(n*m),其中 n 和 m 分别是 矩阵 grid 的行数和列数。
空间复杂度:O(1)。
题目3:3196. 最大化子数组的总成本
思路
因为要解决的问题都形如「a[0] 到 a[i] 的最大成本和」,所以用它作为本题的状态定义 dfs(i)。
分类讨论:
- 分成长为 1 的子数组,即 a[i] 单独作为一个长为 1 的子数组,接下来需要解决的问题为:a[0] 到 a[i−1] 的最大成本和,即 dfs(i)=dfs(i−1)+a[i]。
- 分成长为 2 的子数组,即 a[i−1] 和 a[i] 作为一个长为 2 的子数组,接下来需要解决的问题为:a[0] 到 a[i−2] 的最大成本和,即 dfs(i)=dfs(i−2)+a[i−1]−a[i]。
这两种情况取最大值,就得到了 dfs(i),即:dfs(i)=max(dfs(i−1)+a[i],dfs(i−2)+a[i−1]−a[i])。
递归边界:dfs(−1)=0,dfs(0)=a[0]。
递归入口:dfs(n−1),也就是答案。
代码
#
# @lc app=leetcode.cn id=3196 lang=python3
#
# [3196] 最大化子数组的总成本
#
# @lc code=start
class Solution:
def maximumTotalCost(self, nums: List[int]) -> int:
@cache
def dfs(i: int) -> int:
if i < 0:
return 0
if i == 0:
return nums[0]
return max(dfs(i - 1) + nums[i], dfs(i - 2) + nums[i - 1] - nums[i])
return dfs(len(nums) - 1)
# @lc code=end
复杂度分析
时间复杂度:O(n),其中 n 是数组 nums 的长度。
空间复杂度:O(n),其中 n 是数组 nums 的长度。
题目4:3197. 包含所有 1 的最小矩形面积 II
思路
一共有如下六种情况。

暴力枚举分割线的位置,划分成三个区域,每个区域对应第二题,用第二题的方法求解区域面积最小值。
代码实现时,只需实现上面三种,下面三种可以通过把 grid 顺时针旋转 90° 得到。
代码
/*
* @lc app=leetcode.cn id=3197 lang=cpp
*
* [3197] 包含所有 1 的最小矩形面积 II
*/
// @lc code=start
class Solution
{
// 顺时针旋转矩阵 90°
vector<vector<int>> rotate(vector<vector<int>> &a)
{
int m = a.size();
int n = a[0].size();
vector<vector<int>> b(n, vector<int>(m));
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
b[j][m - 1 - i] = a[i][j];
}
}
return b;
}
int minimumArea(vector<vector<int>> &a, int u, int d, int l, int r)
{
int left = a[0].size(), right = 0, top = a.size(), bottom = 0;
for (int i = u; i < d; i++)
{
for (int j = l; j < r; j++)
{
if (a[i][j] == 1)
{
left = min(left, j);
right = max(right, j);
top = min(top, i);
bottom = i;
}
}
}
return (right - left + 1) * (bottom - top + 1);
}
int f(vector<vector<int>> &a)
{
int ans = INT_MAX;
int m = a.size();
int n = a[0].size();
if (m >= 3)
{
for (int i = 1; i < m; i++)
{
for (int j = i + 1; j < m; j++)
{
// 图片上左
int area = minimumArea(a, 0, i, 0, n);
area += minimumArea(a, i, j, 0, n);
area += minimumArea(a, j, m, 0, n);
ans = min(ans, area);
}
}
}
if (m >= 2 && n >= 2)
{
for (int i = 1; i < m; i++)
{
for (int j = 1; j < n; j++)
{
// 图片上中
int area = minimumArea(a, 0, i, 0, n);
area += minimumArea(a, i, m, 0, j);
area += minimumArea(a, i, m, j, n);
ans = min(ans, area);
// 图片上右
area = minimumArea(a, 0, i, 0, j);
area += minimumArea(a, 0, i, j, n);
area += minimumArea(a, i, m, 0, n);
ans = min(ans, area);
}
}
}
return ans;
}
public:
int minimumSum(vector<vector<int>> &grid)
{
auto g = rotate(grid);
return min(f(grid), f(g));
}
};
// @lc code=end
复杂度分析
时间复杂度:O((n*m)2),其中 n 和 m 分别是 矩阵 grid 的行数和列数。
空间复杂度:O(n*m),其中 n 和 m 分别是 矩阵 grid 的行数和列数。
729

被折叠的 条评论
为什么被折叠?



