11.16
作者:互联网
1658. 将 x 减到 0 的最小操作数
难度中等18
给你一个整数数组 nums
和一个整数 x
。每一次操作时,你应当移除数组 nums
最左边或最右边的元素,然后从 x
中减去该元素的值。请注意,需要 修改 数组以供接下来的操作使用。
如果可以将 x
恰好 减到 0
,返回 最小操作数 ;否则,返回 -1
。
示例 1:
输入:nums = [1,1,4,2,3], x = 5
输出:2
解释:最佳解决方案是移除后两个元素,将 x 减到 0 。
示例 2:
输入:nums = [5,6,7,8,9], x = 4
输出:-1
示例 3:
输入:nums = [3,2,20,1,1,3], x = 10
输出:5
解释:最佳解决方案是移除后三个元素和前两个元素(总共 5 次操作),将 x 减到 0 。
提示:
1 <= nums.length <= 105
1 <= nums[i] <= 104
1 <= x <= 109
解答:前缀和,后缀和,两数之和
class Solution {
public:
int minOperations(vector<int>& nums, int x) {
unordered_map<int, int>cnt;
cnt[0] = -1;
int sum = 0;
int res = INT_MAX;
for(int i = 0; i < nums.size(); i++){
sum += nums[i];
cnt[sum] = i;
}
if(cnt.find(x) != cnt.end())res = min(res, cnt[x] + 1);
sum = 0;
for(int i = nums.size() - 1; i >= 0; i--){
sum += nums[i];
if(cnt.find(x - sum) != cnt.end()){
int ans = nums.size() - i + cnt[x - sum] + 1;
if(ans > nums.size())continue;
res = min(res, ans);
}
}
return res == INT_MAX? -1 : res;
}
};
1423. 可获得的最大点数
难度中等31
几张卡牌 排成一行,每张卡牌都有一个对应的点数。点数由整数数组 cardPoints
给出。
每次行动,你可以从行的开头或者末尾拿一张卡牌,最终你必须正好拿 k
张卡牌。
你的点数就是你拿到手中的所有卡牌的点数之和。
给你一个整数数组 cardPoints
和整数 k
,请你返回可以获得的最大点数。
示例 1:
输入:cardPoints = [1,2,3,4,5,6,1], k = 3
输出:12
解释:第一次行动,不管拿哪张牌,你的点数总是 1 。但是,先拿最右边的卡牌将会最大化你的可获得点数。最优策略是拿右边的三张牌,最终点数为 1 + 6 + 5 = 12 。
示例 2:
输入:cardPoints = [2,2,2], k = 2
输出:4
解释:无论你拿起哪两张卡牌,可获得的点数总是 4 。
示例 3:
输入:cardPoints = [9,7,7,9,7,7,9], k = 7
输出:55
解释:你必须拿起所有卡牌,可以获得的点数为所有卡牌的点数之和。
示例 4:
输入:cardPoints = [1,1000,1], k = 1
输出:1
解释:你无法拿到中间那张卡牌,所以可以获得的最大点数为 1 。
示例 5:
输入:cardPoints = [1,79,80,1,1,1,200,1], k = 3
输出:202
提示:
1 <= cardPoints.length <= 10^5
1 <= cardPoints[i] <= 10^4
1 <= k <= cardPoints.length
解答:还是前缀和思想,计算前面hash[i] + cnt[k - i]和的最大值
class Solution {
public:
int maxScore(vector<int>& nums, int k) {
int res = 0;
unordered_map<int, int>hash,cnt;
int sum = 0;
hash[0] = 0;
cnt[0] = 0;
for(int i = 0; i < nums.size(); i++){
sum += nums[i];
hash[i + 1] = sum;
}
sum = 0;
for(int i = nums.size() - 1, j = 0; i >= 0; i--, j++){
sum += nums[i];
cnt[j + 1] = sum;
}
for(int i = 0; i <= k; i++){
res = max(res, hash[i] + cnt[k - i]);
}
return res;
}
};
406. 根据身高重建队列
难度中等627
假设有打乱顺序的一群人站成一个队列。 每个人由一个整数对(h, k)
表示,其中h
是这个人的身高,k
是排在这个人前面且身高大于或等于h
的人数。 编写一个算法来重建这个队列。
注意:
总人数少于1100人。
示例
输入:
[[7,0], [4,4], [7,1], [5,0], [6,1], [5,2]]
输出:
[[5,0], [7,0], [5,2], [6,1], [4,4], [7,1]]
解答:排序二分,树状数组
class Solution {
public:
int n;
vector<int> tr;
int lowbit(int x) {
return x & -x;
}
void add(int x, int v) {
for (int i = x; i <= n; i += lowbit(i)) tr[i] += v;
}
int query(int x) {
int res = 0;
for (int i = x; i; i -= lowbit(i)) res += tr[i];
return res;
}
vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
n = people.size();
tr.resize(n + 1);
sort(people.begin(), people.end(), [](vector<int>a, vector<int>b) {
if (a[0] != b[0]) return a[0] < b[0];
return a[1] > b[1];
});
vector<vector<int>> res(n);
for (auto p: people) {
int h = p[0], k = p[1];
int l = 1, r = n;
while (l < r) {
int mid = l + r >> 1;
if (mid - query(mid) >= k + 1) r = mid;
else l = mid + 1;
}
res[r - 1] = p;
add(r, 1);
}
return res;
}
};
标签:cnt,nums,11.16,res,sum,int,点数 来源: https://www.cnblogs.com/domy/p/13986308.html