1710. 卡车上的最大单元数-easy-贪心

思路:按照单元素大小进行排序,贪心即可

  1. /**
  2. * @param {number[][]} boxTypes
  3. * @param {number} truckSize
  4. * @return {number}
  5. */
  6. var maximumUnits = function(boxTypes, truckSize) {
  7. let result = 0;
  8. boxTypes.sort((a,b)=>b[1] - a[1]);
  9. boxTypes.map(([num,unit])=>{
  10. result += Math.min(truckSize,num)*unit;
  11. truckSize = Math.max(0,truckSize - num);
  12. })
  13. return result;
  14. };

1711. 大餐计数-medium-哈希表+枚举

  1. /**
  2. * @param {number[]} deliciousness
  3. * @return {number}
  4. */
  5. var countPairs = function(deliciousness) {
  6. const map = new Map();
  7. const mod = 1e9+7;
  8. let result = 0;
  9. deliciousness.map((val)=>{
  10. const cnt = map.get(val) || 0;
  11. for(let j = 0;j < 22;j++){
  12. const target = 2 ** j;
  13. if(map.has(target - val)){
  14. result = (result + map.get(target - val))%mod;
  15. }
  16. }
  17. map.set(val,cnt + 1);
  18. })
  19. return result;
  20. };

1712. 将数组分成三个子数组的方案数-medium-二分

思路:枚举第一段前缀和位置,然后在右侧两次二分查找使其满足题目要求的前缀和位置上界rr和下界ll,在[ll,rr]之间选任一点作为第二个分割点均可满足要求,所以对答案的贡献为 rr- ll + 1

/**
 * @param {number[]} nums
 * @return {number}
 */
var waysToSplit = function(nums) {
  const n = nums.length;
  const pre_sum = new Int32Array(n + 1);
  const mod = 1e9 + 7;
  pre_sum[0] = nums[0];
  for (let i = 1; i < n; i++) {
    pre_sum[i] = pre_sum[i - 1] + nums[i];
  }
  const sum = pre_sum[n - 1];
  let result = 0;
  for (let i = 0; i < n - 1; i++) {
    if (pre_sum[i] * 3 > sum) {
      break;
    }
    let [l, r, ll, rr] = [i + 1, n - 2];
    while (l <= r) {
      const mid = (l + r) >> 1;
      if (pre_sum[mid] >= 2 * pre_sum[i]) {
        r = mid - 1;
      } else {
        l = mid + 1;
      }
    }
    ll = l;
    [l, r] = [i + 1, n - 2];
    while (l <= r) {
      const mid = (l + r) >> 1;
      if (sum - pre_sum[mid] >= pre_sum[mid] - pre_sum[i]) {
        l = mid + 1;
      } else {
        r = mid - 1;
      }
    }
    rr = r;
    result += (rr - ll + 1) % mod;
  }
  return result % mod;
};

1713. 得到子序列的最少操作次数-hard-LIS

思路:设target长度为N,假设需要添加x个整数,那么就需要arr 提供N-x个整数,而且这N-x个整数在target中的相对顺序还必须与target的相同,为了使x最小,则需要让N-x最大,即找出arr中满足顺序相同的最长上升子序列因为是最长(严格)递增子序列,所以可以使用O(NlogN)的做法来优化效率。

/**
 * @param {number[]} target
 * @param {number[]} arr
 * @return {number}
 */
const lower_bound = (arr, left, right, val) => {
  while (left <= right) {
    const mid = (left + right) >> 1;
    if (arr[mid] === val) {
      return mid;
    } else if (arr[mid] < val) {
      left = mid + 1;
    } else {
      right = mid - 1;
    }
  }
  return left;
}
const LIS = (arr) => {
  const n = arr.length;
  const res = [];
  for (let i = 0; i < n; i++) {
    if (!res.length || arr[i] > res[res.length - 1]) {
      res.push(arr[i]);
    } else {
      const index = lower_bound(res, 0, res.length - 1, arr[i]);
      res[index] = arr[i];
    }
  }
  return res.length;
}
var minOperations = function(target, arr) {
  const map = new Map();
  const indexs = [];
  for (let i = 0; i < target.length; i++) {
    map.set(target[i], i);
  }
  arr.map(item => {
    if (map.has(item)) {
      indexs.push(map.get(item));
    }
  })
  return target.length - LIS(indexs);
};