持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情
题目描述
小力将 N 个零件的报价存于数组 nums。小力预算为 target,假定小力仅购买两个零件,要求购买零件的花费不超过预算,请问他有多少种采购方案。
注意:答案需要以 1e9 + 7 (1000000007) 为底取模,如:计算初始结果为:1000000008,请返回 1
示例 1:
输入: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
双指针
这个题目我的初步思路是:双指针的基本解法,通过双指针找到符合条件最大值nums[right]跟最小值nums[left]的区间,则最小值能组成的个数就是right - left。对于i而言,满足target内的商品是右边第一个不满足为止之间的所有商品,而对于i后面的所有的商品来说,i不满足的话,i+1也不满足,因此右边的边界可以在每一次的循环之间更新,从而大大减少需要遍历的次数,而由于是两两选择商品,对于[i, j]区间内的商品个数就直接等于j-i了。那么具体实现的方式如下:
当left < right或者nums[left] < target, 因为两个数的和小于target,哪门我们就可以进入循环进行处理。
当如果nums[left] >= target时,则直接退出循环就行了
如果区间条件left < right && nums[left] + nums[right] > target成立,那么我们让right--往回移动
每个循环节结束前,进行累计结果就行了。
class Solution {
public int purchasePlans(int[] nums, int target) {
long count = 0;
int j = nums.length - 1;
Arrays.sort(nums);
if (nums[0] >= target) return 0;
for(int i = 0;i < nums.length;i++){
while(nums[i] +nums[j] > target && j > 0) j--;
if(i >= j) break;
count += j - i;
}
return (int)(count % 1000000007);
}
}
最后
注意:题目的要求共有 left + 1 个和 right 能够配上,但是这种情况漏掉了下标 [0, left] 的组合,可以在最后确定了 left 位置之后统一确定,因为最后指针停留的位置没办法很好的确定,所以就美珍明白,但这个问题应该不复杂,如果题目共有 right - left 个和 left 匹配,此后 left 继续向右走,过往没落下啥。 总结:反过来想,问题可以取补解决,解决过程也可以取补;眼高手低的在那想。