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 的行数和列数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UestcXiye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值