【算法】JS DP 二分 力扣6346. 打家劫舍 IV

题目链接

6346. 打家劫舍 IV

题目描述

沿街有一排连续的房屋。每间房屋内都藏有一定的现金。现在有一位小偷计划从这些房屋中窃取现金。

由于相邻的房屋装有相互连通的防盗系统,所以小偷 不会窃取相邻的房屋 。

小偷的 窃取能力 定义为他在窃取过程中能从单间房屋中窃取的 最大金额 。

给你一个整数数组 nums 表示每间房屋存放的现金金额。形式上,从左起第 i 间房屋中放有 nums[i] 美元。

另给你一个整数数组 k ,表示窃贼将会窃取的 最少 房屋数。小偷总能窃取至少 k 间房屋。

返回小偷的 最小 窃取能力。

题解

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var minCapability = function (nums, k) {
  // 最小窃取能力显然是与房屋金额有关

  // 对窃取能力值去重 从小到大排序
  const arr = Array.from(new Set(nums)).sort((x, y) => x - y);

  // 二分
  let left = 0, right = arr.length - 1
  while (left <= right) {
    const mid = ((left + right) >> 1)
    const cap = arr[mid]; // 当前能力值
    let dp_2 = 0, dp_1 = 0 // 当前-2最多偷几家 当前-1最多偷几家
    for (let i = 0; i < nums.length; i++) {
      let dp_0 // 当前最多偷几家
      if (nums[i] <= cap) { // 可以偷
        dp_0 = Math.max(dp_2 + 1, dp_1);
      } else { // 不能偷
        dp_0 = Math.max(dp_2, dp_1)
      }
      
      [dp_2, dp_1] = [dp_1, dp_0]
    }

    if (Math.max(dp_2, dp_1) < k) left = mid + 1 // 需要加强窃取能力才能达到要求
    else right = mid - 1 // 当前窃取能力已经达到要求 尝试减少点能力
  }
  return arr[left]
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值