LCP 28. 采购方案(双指针、二分)

183 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

每日刷题第72天 2021.03.30

LCP 28. 采购方案

题目描述

  • 小力将 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

解题思路

  • 根据题意:需要任意选择两个零件,不能超过预算target
  • 预处理:排序,将数组按非递减的顺序排列。
  • 双指针:维护右端点,对于每一个右端点都可以往后找到匹配的数
    • 举例:nums = [1,2,2,9]
    • 对于第一个右端点1,其可以匹配1,21,21,9
    • 对于第二个右端点2可以匹配2,22,9;
    • 对于第三个右端点2可以匹配2,9
    • 对于第四个右端点9,其是最后一个,没有可以与之匹配的零件
  • 根据上述的分析可得:
    • 对于右端点1而言,如果1 + 9 <= target,那么比数组中9所在的下标小的元素,和右端点1的加和,也一定<= target
    • 对于其他的右端点同理
    • 因此:对于右端点1符合的有1,21,21,9;对于右端点2符合的有2,2

AC代码

var purchasePlans = function(nums, target) {
  nums.sort((a, b) => a - b);
  let pre = 0,len = nums.length,last = len - 1;
  let sum = 0;
  while(pre < last) {
    if(target >= nums[pre] + nums[last]){
      // 找到界限
      sum += last - pre;
      pre++;
    }else {
      // 没有找到界限
      last--;
    }
  }
  return sum % 1000000007;
};

总结

  • 双指针的做法比较精妙,重在思维上的理解