Leetcode 第 404 场周赛题解

Leetcode 第 404 场周赛题解

题目1:3200. 三角形的最大高度

思路

枚举第一行是红色还是蓝色,再按题意模拟即可。

代码

/*
 * @lc app=leetcode.cn id=3200 lang=cpp
 *
 * [3200] 三角形的最大高度
 */

// @lc code=start
class Solution
{
public:
    int maxHeightOfTriangle(int red, int blue)
    {
        if (red <= 0 || blue <= 0)
            return 0;

        return max(helper(red, blue), helper(blue, red));
    }
    // 辅助函数
    int helper(int x, int y)
    {
        int level = 0;
        while (x >= 0 && y >= 0)
        {
            if (level % 2 == 0)
            {
                x -= (level + 1);
                if (x < 0)
                    break;
            }
            else
            {
                y -= (level + 1);
                if (y < 0)
                    break;
            }
            level++;
        }
        return level;
    }
};
// @lc code=end

复杂度分析

时间复杂度:O(min(sqrt(red), sqrt(blue)))。

空间复杂度:O(1)。

题目2:3201. 找出有效子序列的最大长度 I

思路

全奇数、全偶数、奇偶交替三种情况的最大值即为所求。

代码

/*
 * @lc app=leetcode.cn id=3201 lang=cpp
 *
 * [3201] 找出有效子序列的最大长度 I
 */

// @lc code=start
class Solution
{
public:
    int maximumLength(vector<int> &nums)
    {
        // 分三种情况:全奇、全偶、奇偶交替
        int odd = 0, even = 0;
        for (int &num : nums)
        {
            if (num % 2)
                odd++;
            else
                even++;
        }
        int interlaced = 1, tag = nums[0];
        for (int i = 1; i < nums.size(); i++)
            if ((nums[i] & 1) ^ (tag & 1))
            {
                interlaced++;
                tag = nums[i];
            }
        return max(interlaced, max(odd, even));
    }
};
// @lc code=end

复杂度分析

时间复杂度:O(n),其中 n 是数组 nums 的长度。

空间复杂度:O(1)。

题目3:3202. 找出有效子序列的最大长度 II

思路

本题是选与不选的子序列问题,可以尝试给出这样的状态定义:

dp[i][j]:以 nums[i] 结尾模 k 后值为 j 的最长子序列的长度。

那么状态转移方程是怎样的呢?对于每一个 i,遍历 j(0<=j<i),dp[i][(nums[i] + nums[j]) % k] = dp[j][(nums[i] + nums[j]) % k] + 1,保证模 k 后的值相同。

代码

/*
 * @lc app=leetcode.cn id=3202 lang=cpp
 *
 * [3202] 找出有效子序列的最大长度 II
 */

// @lc code=start
class Solution
{
public:
    int maximumLength(vector<int> &nums, int k)
    {
        int n = nums.size();
        // dp[i][j]: 以 nums[i] 结尾模 k 后值为 j 的最长子序列的长度
        vector<vector<int>> dp(n, vector<int>(k, 0));
        // 初始化
        for (int i = 0; i < n; i++)
            dp[i][0] = 1;
        int ans = 1;
        // 状态转移
        for (int i = 1; i < n; i++)
            for (int j = 0; j < i; j++)
            {
                dp[i][(nums[i] + nums[j]) % k] = dp[j][(nums[i] + nums[j]) % k] + 1;
                ans = max(ans, dp[i][(nums[i] + nums[j]) % k]);
            }
        return ans;
    }
};
// @lc code=end

复杂度分析

时间复杂度:O(n2),其中 n 是数组 nums 的长度。

空间复杂度:O(n*k),其中 n 是数组 nums 的长度。

题目4:3203. 合并两棵树后的最小直径

思路

题解:连接直径中点(Python/Java/C++/Go)

代码

/*
 * @lc app=leetcode.cn id=3203 lang=cpp
 *
 * [3203] 合并两棵树后的最小直径
 */

// @lc code=start
class Solution
{
private:
    // 求树的直径
    int diameter(vector<vector<int>> &edges)
    {
        vector<vector<int>> g(edges.size() + 1);
        for (auto &e : edges)
        {
            int x = e[0], y = e[1];
            g[x].push_back(y);
            g[y].push_back(x);
        }

        int res = 0;
        auto dfs = [&](auto &&dfs, int x, int fa) -> int
        {
            int max_len = 0;
            for (auto y : g[x])
            {
                if (y != fa)
                {
                    int sub_len = dfs(dfs, y, x) + 1;
                    res = max(res, max_len + sub_len);
                    max_len = max(max_len, sub_len);
                }
            }
            return max_len;
        };
        dfs(dfs, 0, -1);
        return res;
    }

public:
    int minimumDiameterAfterMerge(vector<vector<int>> &edges1, vector<vector<int>> &edges2)
    {
        // 设树 1 的长度为 d1
        int d1 = diameter(edges1);
        // 设树 2 的长度为 d2
        int d2 = diameter(edges2);
        // 答案为三种情况的最大值:
        // 1. d1
        // 2. d2
        // 3. 连接两棵树的直径中点,(d1 + 1) / 2 + (d2 + 1) / 2 + 1
        return max(max(d1, d2), (d1 + 1) / 2 + (d2 + 1) / 2 + 1);
    }
};
// @lc code=end

复杂度分析

时间复杂度:O(n+m),其中 n 是数组 edges1 的长度,m 是数组 edges2 的长度。

空间复杂度:O(n+m),其中 n 是数组 edges1 的长度,m 是数组 edges2 的长度。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

UestcXiye

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

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

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

打赏作者

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

抵扣说明:

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

余额充值