前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Leetcode 周赛题解222

Leetcode 周赛题解222

作者头像
ACM算法日常
发布2021-01-13 10:19:53
5370
发布2021-01-13 10:19:53
举报
文章被收录于专栏:ACM算法日常

难度顺序:

A\le B\le C\le D

5641. 卡车上的最大单元数

请你将一些箱子装在 一辆卡车 上。给你一个二维数组 boxTypes ,其中 boxTypes[i] = [numberOfBoxesi, numberOfUnitsPerBoxi]

  • numberOfBoxesi 是类型 i 的箱子的数量。
  • numberOfUnitsPerBoxi 是类型 i 每个箱子可以装载的单元数量。

整数 truckSize 表示卡车上可以装载 箱子最大数量 。只要箱子数量不超过 truckSize ,你就可以选择任意箱子装到卡车上。

返回卡车可以装载 单元最大 总数*。*

示例 1:

代码语言:javascript
复制
输入:boxTypes = [[1,3],[2,2],[3,1]], truckSize = 4
输出:8
解释:箱子的情况如下:
- 1 个第一类的箱子,里面含 3 个单元。
- 2 个第二类的箱子,每个里面含 2 个单元。
- 3 个第三类的箱子,每个里面含 1 个单元。
可以选择第一类和第二类的所有箱子,以及第三类的一个箱子。
单元总数 = (1 * 3) + (2 * 2) + (1 * 1) = 8

示例 2:

代码语言:javascript
复制
输入:boxTypes = [[5,10],[2,5],[4,7],[3,9]], truckSize = 10
输出:91

提示:

  • 1 <= boxTypes.length <= 1000
  • 1 <= numberOfBoxesi, numberOfUnitsPerBoxi <= 1000
  • ``1 <= truckSize <= 10^6`

思路:

既然选择箱子的个数有限制,我们就贪心的选择容量最大的箱子。将箱子按照容量排序之后依次取即可。

时间复杂度:

O(n*log(n))

.

代码语言:javascript
复制
class Solution {
public:
    int maximumUnits(vector<vector<int>>& boxTypes, int truckSize) {
        auto cmp = [&](vector<int> &a, vector<int> &b) {
            return a[1] > b[1];
        };
        sort(boxTypes.begin(), boxTypes.end(), cmp);
        int ans = 0;
        for(vector<int> &x: boxTypes) {
            if(truckSize == 0) break;
            int tmp = min(truckSize, x[0]);
            ans += x[1] * tmp;
            truckSize -= tmp;
        }
        return ans;
    }
};

5642. 大餐计数

大餐 是指 恰好包含两道不同餐品 的一餐,其美味程度之和等于 2 的幂。

你可以搭配 任意 两道餐品做一顿大餐。

给你一个整数数组 deliciousness ,其中 deliciousness[i] 是第 i 道餐品的美味程度,返回你可以用数组中的餐品做出的不同 大餐 的数量。结果需要对 109 + 7 取余。

注意,只要餐品下标不同,就可以认为是不同的餐品,即便它们的美味程度相同。

示例 1:

代码语言:javascript
复制
输入:deliciousness = [1,3,5,7,9]
输出:4
解释:大餐的美味程度组合为 (1,3) 、(1,7) 、(3,5) 和 (7,9) 。
它们各自的美味程度之和分别为 4 、8 、8 和 16 ,都是 2 的幂。

示例 2:

代码语言:javascript
复制
输入:deliciousness = [1,1,1,3,3,3,7]
输出:15
解释:大餐的美味程度组合为 3 种 (1,1) ,9 种 (1,3) ,和 3 种 (1,7) 。

提示:

  • 1 <= deliciousness.length <= 10^5
  • 0 <= deliciousness[i] <= 2^20

思路:

美味度最大只有

2^{20}

,我们枚举每一道菜和

2

的幂次方即可。

时间复杂度:

O(n*log(n))

.

代码语言:javascript
复制
const int mod = 1e9 + 7;
class Solution {
public:
    int countPairs(vector<int>& deliciousness) {
        vector<int> vis((1<<20)+1, 0);
        int ans = 0;
        for(int x: deliciousness) {
            for(int i = 0; i < 22; ++i) {
                if(x <= (1 << i) && (1 << i) - x <= (1<<20)) ans = (ans + vis[(1<<i) - x]) % mod;
            }
            ++ vis[x];
        }
        return ans;
    }
};

5643. 将数组分成三个子数组的方案数

我们称一个分割整数数组的方案是 好的 ,当它满足:

  • 数组被分成三个 非空 连续子数组,从左至右分别命名为 leftmidright
  • left 中元素和小于等于 mid 中元素和,mid 中元素和小于等于 right 中元素和。

给你一个 非负 整数数组 nums ,请你返回 好的 分割 nums 方案数目。由于答案可能会很大,请你将结果对 109 + 7 取余后返回。

示例 1:

代码语言:javascript
复制
输入:nums = [1,1,1]
输出:1
解释:唯一一种好的分割方案是将 nums 分成 [1] [1] [1] 。

示例 2:

代码语言:javascript
复制
输入:nums = [1,2,2,2,5,0]
输出:3
解释:nums 总共有 3 种好的分割方案:
[1] [2] [2,2,5,0]
[1] [2,2] [2,5,0]
[1,2] [2,2] [5,0]

示例 3:

代码语言:javascript
复制
输入:nums = [3,2,1]
输出:0
解释:没有好的分割方案。

提示:

  • 3 <= nums.length <= 10^5
  • 0 <= nums[i] <= 10^4

思路

要求将序列分成三段,每段数值之和不递减的合法方案数。

我们枚举第一段的位置,然后二分两次。

第一次二分中间这一段的右端点最小可以是多少。

第二次二分中间这一段的右端点最大可以是多少。

注意二分的时候要合法转移,详见代码。

时间复杂度:

O(n*log(n))

.

代码语言:javascript
复制
const int mod = 1e9 + 7;
class Solution {
public:
    int waysToSplit(vector<int>& nums) {
        int ans = 0, n = nums.size();
        vector<int64_t> pre(n, 0);
        pre[0] = nums[0];
        for(int i = 1; i < n; ++i) pre[i] = pre[i - 1] + nums[i];
        for(int i = 0; i + 2 < n; ++i) {
            int L = i + 1, R = n - 2, mid, ans1 = -1, ans2 = -1;
            while(L <= R) {
                mid = (L + R) >> 1;
                if(pre[mid] - pre[i] >= pre[i] && pre[n - 1] - pre[mid] >= pre[mid] - pre[i]) ans1 = mid, R = mid - 1;
                else if(pre[n - 1] - pre[mid] < pre[mid] - pre[i]) R = mid - 1;//最右侧的一段权值和较小,要右移
                else if(pre[mid] - pre[i] < pre[i]) L = mid + 1;//中间这一段权值和较小,要左移。
                else break;
            }
            L = i + 1, R = n - 2;
            while(L <= R) {
                mid = (L + R) >> 1;
                if(pre[mid] - pre[i] >= pre[i] && pre[n - 1] - pre[mid] >= pre[mid] - pre[i]) ans2 = mid, L = mid + 1;
                else if(pre[n - 1] - pre[mid] < pre[mid] - pre[i]) R = mid - 1;
                else if(pre[mid] - pre[i] < pre[i]) L = mid + 1;
                else break;
            }
            if(ans1 != -1 && ans2 != -1) ans = (ans + ans2 - ans1 + 1) % mod;
        }
        return ans;
    }
};

5644. 得到子序列的最少操作次数

给你一个数组 target ,包含若干 互不相同 的整数,以及另一个整数数组 arrarr 可能 包含重复元素。

每一次操作中,你可以在 arr 的任意位置插入任一整数。比方说,如果 arr = [1,4,1,2] ,那么你可以在中间添加 3 得到 [1,4,3,1,2] 。你可以在数组最开始或最后面添加整数。

请你返回 最少 操作次数,使得 target 成为 arr 的一个子序列。

一个数组的 子序列 指的是删除原数组的某些元素(可能一个元素都不删除),同时不改变其余元素的相对顺序得到的数组。比方说,[2,7,4][4,2,3,7,2,1,4] 的子序列,但 [2,4,2] 不是子序列。

示例 1:

代码语言:javascript
复制
输入:target = [5,1,3], arr = [9,4,2,3,4]
输出:2
解释:你可以添加 5 和 1 ,使得 arr 变为 [5,9,4,1,2,3,4] ,target 为 arr 的子序列。

示例 2:

代码语言:javascript
复制
输入:target = [6,4,8,1,3,2], arr = [4,7,6,2,3,8,6,1]
输出:3

提示:

  • 1 <= target.length, arr.length <= 105
  • 1 <= target[i], arr[i] <= 109
  • target 不包含任何重复元素。

思路

最少要在arr中插入元素的个数使得targetarr的一个子序列,其实就是求两个序列的最长公共子序列长度。

注意到target中不包含重复的元素,那么其实arr中那些没在target中出现的元素都可以扔掉不管。

因为target不包含重复的元素,我们将元素重新编号。在target中第

i

个数字重新编号为

i

。然后arr数组也按照这个重新编号。

最后这个最长公共子序列的长度其实就等于arr的最长上升子序列的长度。

时间复杂度:

O(n*log(n))

.

代码语言:javascript
复制
class Solution {
public:
    int minOperations(vector<int>& target, vector<int>& arr) {
        int n = target.size(), m = arr.size();
        map<int, int> mp;
        vector<int> dp(m, 0x3f3f3f3f);
        for(int i = 0; i < n; ++i) mp[target[i]] = i + 1;
        int Mx = 0;
        for(int i = 0; i < m; ++i) {
            if(mp[arr[i]] == 0) continue;
            arr[i] = mp[arr[i]];
            int p = lower_bound(dp.begin(), dp.end(), arr[i]) - dp.begin();
            dp[p] = arr[i];
            Mx = max(Mx, p + 1);
        }
        return n - Mx;
    }
};
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-01-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ACM算法日常 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 5641. 卡车上的最大单元数
  • 5642. 大餐计数
  • 5643. 将数组分成三个子数组的方案数
  • 5644. 得到子序列的最少操作次数
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档