力扣——2560. 打家劫舍 IV

力扣——2560. 打家劫舍 IV

在这里插入图片描述

题目描述:

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

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

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

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

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

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

示例 :

输入:nums = [2,3,5,9], k = 2
输出:5
解释:
小偷窃取至少 2 间房屋,共有 3 种方式:
- 窃取下标 0 和 2 处的房屋,窃取能力为 max(nums[0], nums[2]) = 5 。
- 窃取下标 0 和 3 处的房屋,窃取能力为 max(nums[0], nums[3]) = 9 。
- 窃取下标 1 和 3 处的房屋,窃取能力为 max(nums[1], nums[3]) = 9 。
因此,返回 min(5, 9, 9) = 5 。

分析:

​ 力扣的每日一题真的是和小偷杠上了哈哈,连续做了三天打家劫舍。这题一开始没有思路,后面看了题解才解出来的,拖了大伙的后腿。

题目理解

  1. 不会窃取相邻房屋 dp[i] = max(dp[i-1],dp[i-2]+v) 大概是这种格式的动态规划
  2. 窃贼最少窃取 k 间房屋的情况下,让单间房屋窃取的最大金额最小,最大值最小问题,可以用二分答案解决
思路
  1. 求出数组中的最大最小值,答案一定就在这些值之中,得到二分的范围
  2. 假设房前窃取的最大金额是 x, 那么如果当前房屋超过了 x,则无法窃取当前房屋
  3. 否则可以窃取当前房屋计数 1,也就是 max(dp[i-1],dp[i-2]+v) 这个里面的 v 值看当前金额与 x 的比较结果,不超过 x 计数 1,否则为 0
  4. 如果再窃取能力是 x 的情况下,能窃取到 k 间以上的房屋,则尝试缩小窃取能力(因为答案要最小的窃取能力)
  5. 否则说明 x 不是可行解,需要找到 x+1 以上的房屋才能获得到可行解

代码解析:

class Solution2560 {
        public int minCapability(int[] nums, int k) {
            int n = nums.length;
            if(n==1) return nums[0];
            int left = Integer.MAX_VALUE;
            int right = Integer.MIN_VALUE;
            for(int num:nums){
                left = Math.min(num,left);
                right = Math.max(num,right);
            }
            while(left<right){
                int mid = (right-left)/2+left;
                if(check(nums,mid,k)){
                    right = mid;
                }else{
                    left = mid+1;
                }
            }
            return right;
        }
        private boolean check(int[] nums, int v, int k){
            int n = nums.length;
            long[] dp = new long[n];
            dp[0]=nums[0]<=v?1:0;
            dp[1]=nums[1]<=v?1:0;
            dp[1] = Math.max(dp[0],dp[1]);
            for(int i = 2; i < n; i++){
                int add = nums[i]<=v?1:0;
                dp[i] = Math.max(add+dp[i-2],dp[i-1]);
            }
            return dp[n-1]>=k;
        }
    }

感谢您的观看,我的博客地址:http://47.115.223.247:2001/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值