Lccup 力扣杯春季编程大赛 1、采购方案
题目描述
小力将 N 个零件的报价存于数组 nums。小力预算为 target,假定小力仅购买两个零件,要求购买零件的花费不超过预算,请问他有多少种采购方案。
注意:答案需要以 1e9 + 7 (1000000007) 为底取模,如:计算初始结果为:1000000008,请返回 1
示例 1:
输入:nums = [2,5,3,5], target = 6
输出:1
解释:预算内仅能购买 nums[0] 与 nums[2]。
示例 2:
输入:nums = [2,2,1,9], target = 10
输出:4
解释:符合预算的采购方案如下:
nums[0] + nums[1] = 4
nums[0] + nums[2] = 3
nums[1] +nums[2] = 3
nums[2] + nums[3] = 10
提示:
- 2 <= nums.length <= 10^5
- 1 <= nums[i], target <= 10^5
思路
排序,然后遍历每个报价,累加每个报价和后面的报价可能组合,然后取模
如何计算每个报价和后面的报价可能组合?用二分查找找到第一个比 taget - 当前报价
大的报价下标位置,两个下标的位置相减就是可能组合个数
class Solution {
public:
int purchasePlans(vector<int>& nums, int target) {
sort(nums.begin(),nums.end());
int last=0,res=0,temp=0,n=nums.size();
for(int i=0;i<n;++i){
last=target-nums[i];
//二分查找找到下标,从当前下标的后一个开始找,为什么事last+1呢,是因为lower_bound事查找第一个大于等于的,
//所以要加一,不然找到等于的,而等于的刚好有多个,那不就漏算,可以改用upper_bound,查找第一个大于的
temp=lower_bound(nums.begin()+i+1,nums.end(),last+1)-(nums.begin()+i+1);
res=(res+temp)%int(1e9+7);
}
return res;
}
};
可以改用upper_bound,查找第一个大于的也是通过的
temp=upper_bound(nums.begin()+i+1,nums.end(),last)-(nums.begin()+i+1);
别人的做法
类似于双指针,找第一个比 taget - 当前报价
大的,看了好几个都是这么做的
class Solution {
public:
int purchasePlans(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());
int j = (int)nums.size() - 1;
long long sum = 0;
for (int i = 0; i < nums.size(); ++i) {
while (j > i && nums[i] + nums[j] > target) {
--j;
}
if (j > i)
sum += j - i;
}
return sum % 1000000007;
}
};