Leetcode双周赛120总结

Q1 统计移除递增子数组的数目I

  • 题目链接
  • 解题思路:
    • Q3的简单版本
    • 解题思路同Q3

Q2 找到最大周长的多边形

  • 题目链接

  • 解题思路:

    • 先排序
    • 计算前缀和
    • 对于每一个ai,在其前面的所有元素的和最大值就是[a0, ai-1]所有元素的和,如果该和大于ai,则可以得到一个由[a0, ai]组成的多边形,更新周长
  • 解题代码:


class Solution {
public:
    long long largestPerimeter(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        int n = nums.size();
        vector<long long> s(n+1, 0);
        for (int i = 1; i <= n; i++) {
            s[i] = s[i-1] + nums[i-1];
        }
        long long ans = -1;
        for (int i = 2; i < n; i++) {
            if (s[i] > nums[i]) {
                ans = max(ans, s[i] + nums[i]);
            }
        }
        return ans;
    }
};

Q3 统计移除递增子数组的数目II

  • 题目链接

  • 解题思路:

    • 先找后缀最早从哪里开始严格递增
    • 枚举开始删除位置i:
      • 二分找到严格递增后缀中,第一个严格大于ai-1的位置idx,以i为开始删除位置的删除方案数为n-idx+1
      • 枚举到产生第一个不满足前缀严格递增的位置为止
  • 解题代码:


class Solution {
public:
    long long incremovableSubarrayCount(vector<int>& nums) {
        int n = nums.size();
        int start = n-1;
        for (int i = n-2; i >= 0; i--) {
            if (nums[i] >= nums[i+1]) {
                break;
            }
            start -= 1;
        }
        long long ans = 0;
        // start 是后缀最早开始递增的位置
        for (int i = 0; i < n; i++) {
            int pre = i == 0 ? -1 : nums[i-1];
            int l = start, r = n-1;
            while (l <= r) {
                int m = l + (r - l) / 2;
                if (nums[m] > pre) {
                    r = m - 1;
                } else {
                    l = m + 1;
                }
            }
            ans += (n - l + 1);
            if (l == i) {
                ans -= 1;
            }
            if (i != 0 && nums[i] <= nums[i-1]) {
                break;
            }
        }
        return ans;
    }
};

Q4 树中每个节点放置的金币数目

  • 题目链接

  • 解题思路:

    • 在dfs的过程中,保存每个子树中最大的三个以及最小的两个结点的cost,对应开销乘积最大值的两种情况:
      • 最大值1 * 最大值2 * 最大值3,三个数均为正数
      • 最大值1 * 最小值1 * 最小值2,最大值为正数,两个最小值均为负数
    • 维护子树信息时可以用归并排序
  • 解题代码:


class Solution {
public:
    vector<long long> placedCoins(vector<vector<int>>& edges, vector<int>& cost) {
        int n = cost.size();
        vector<long long> ans(n);
        vector<vector<int>> g(n);
        for (auto &edge : edges) {
            int x = edge[0];
            int y = edge[1];
            g[x].push_back(y);
            g[y].push_back(x);
        }
        auto unite = [](vector<long long>& a, vector<long long>& b) {
            vector<long long> temp(6);
            int idx1 = 0, idx2 = 0;
            int idx = 0;
            while (idx < 3) {
                if (a[idx1] > b[idx2]) {
                    temp[idx++] = a[idx1++];
                } else {
                    temp[idx++] = b[idx2++];
                }
            }
            idx1 = idx2 = 3;
            while (idx < 5) {
                if (a[idx1] < b[idx2]) {
                    temp[idx++] = a[idx1++];
                } else {
                    temp[idx++] = b[idx2++];
                }
            }
            temp[5] = a.back() + b.back();
            a = move(temp);
        };
        function<vector<long long>(int, int)> dfs = [&](int x, int fa) -> vector<long long> {
            vector<long long> costs = {INT_MIN, INT_MIN, INT_MIN, INT_MAX, INT_MAX, 0}; // 最大的三个数 + 最小的两个数
            for (auto y : g[x]) {
                if (y == fa) {
                    continue;
                }
                auto children = dfs(y, x);
                // 更新costs
                unite(costs, children);
            }
            vector<long long> new_node = {cost[x], INT_MIN, INT_MIN, cost[x], INT_MAX, 1};
            unite(costs, new_node);
            if (costs.back() < 3) {
                ans[x] = 1;
                return costs;
            }
            long long temp1 = INT_MIN, temp2 = INT_MIN;
            if (costs[0] > INT_MIN && costs[1] > INT_MIN && costs[2] > INT_MIN) {
                temp1 = costs[0] * costs[1] * costs[2];
            }
            if (costs[0] > INT_MIN && costs[3] < INT_MAX && costs[4] < INT_MAX) {
                temp2 = costs[0] * costs[3] * costs[4];
            }
            long long temp = max(temp1, temp2);
            if (temp == INT_MIN) {
                ans[x] = 1;
            } else if (temp < 0) {
                ans[x] = 0;
            } else {
                ans[x] = temp;
            }
            return costs;
        };
        dfs(0, -1);
        return ans;
    }
};

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值