Leetcode.2560 打家劫舍 IV

题目链接

Leetcode.2560 打家劫舍 IV rating : 2081

题目描述

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

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

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

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

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

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

示例 1:

输入: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 。

示例 2:

输入:nums = [2,7,9,3,1], k = 2

输出:2

解释:共有 7 种窃取方式。窃取能力最小的情况所对应的方式是窃取下标 0 和 4 处的房屋。返回 max(nums[0], nums[4]) = 2 。

提示:

  • 1 ≤ n u m s . l e n g t h ≤ 1 0 5 1 \leq nums.length \leq 10^5 1≤nums.length≤105
  • 1 ≤ n u m s [ i ] ≤ 1 0 9 1 \leq nums[i] \leq 10^9 1≤nums[i]≤109
  • 1 ≤ k ≤ ( n u m s . l e n g t h + 1 ) / 2 1 \leq k \leq (nums.length + 1)/2 1≤k≤(nums.length+1)/2

解法:二分 + dp

我们定义 f ( i , x ) f(i,x) f(i,x) 为 能从 n u m s nums nums前 i i i 个房间中选的 不大于 x x x 的最多房间个数。

如果 f ( n , x ) ≥ k f(n,x) \geq k f(n,x)≥k ,说明 能找到 至少 k k k 个 不大于 x x x 的房间,那么 x x x 就是答案之一。

如果 f ( n , x ) < k f(n,x) < k f(n,x)<k ,说明 不能找到 至少 k k k 个 不大于 x x x 的房间,那么我们需要适当的增大 x x x。

所以我们可以使用二分,来得到一个最小的满足要求的 x x x,就是答案。

对于 n u m s [ i ] nums[i] nums[i],我们需要讨论:

  • 如果 n u m s [ i ] > x nums[i] > x nums[i]>x,说明当前 n u m s [ i ] nums[i] nums[i] 我们是不能选的,所以 f ( i ) = f ( i − 1 ) f(i) = f(i - 1) f(i)=f(i−1);
  • 如果 n u m s [ i ] ≤ x nums[i] \leq x nums[i]≤x,说明当前 n u m s [ i ] nums[i] nums[i] 我们可以选,所以 f ( i ) = m a x { f ( i ) , f ( i − 2 ) + 1 } f(i) = max \{ f(i) ,f(i - 2) + 1 \} f(i)=max{f(i),f(i−2)+1};

在实现上我们可以只使用两个变量 f 0 f0 f0 和 f 1 f1 f1 来代替数组。

时间复杂度: O ( n × l o g n ) O(n \times logn) O(n×logn)

C++代码:

cpp 复制代码
class Solution {
public:
    int minCapability(vector<int>& nums, int k) {
        int n = nums.size();

        auto check = [&](int t) -> bool{
            int f0 = 0 , f1 = 0;
            for(auto x:nums){
                if(x > t) f0 = f1;
                else{
                    int temp = f1;
                    f1 = max(f1,f0 + 1);
                    f0 = temp;
                }
            }
            return f1 >= k;
        };

        int l = 0 , r = 1e9;
        while(l < r){
            int mid = (l + r) >> 1;
            if(check(mid)) r = mid;
            else l = mid + 1;
        }

        return l;
    }
};
相关推荐
森焱森1 小时前
无人机三轴稳定化控制(1)____飞机的稳定控制逻辑
c语言·单片机·算法·无人机
循环过三天1 小时前
3-1 PID算法改进(积分部分)
笔记·stm32·单片机·学习·算法·pid
蓝澈11211 小时前
弗洛伊德(Floyd)算法-各个顶点之间的最短路径问题
java·数据结构·动态规划
闪电麦坤951 小时前
数据结构:二维数组(2D Arrays)
数据结构·算法
凌肖战1 小时前
力扣网C语言编程题:快慢指针来解决 “寻找重复数”
c语言·算法·leetcode
埃菲尔铁塔_CV算法2 小时前
基于 TOF 图像高频信息恢复 RGB 图像的原理、应用与实现
人工智能·深度学习·数码相机·算法·目标检测·计算机视觉
NAGNIP3 小时前
一文搞懂FlashAttention怎么提升速度的?
人工智能·算法
Codebee3 小时前
OneCode图生代码技术深度解析:从可视化设计到注解驱动实现的全链路架构
css·人工智能·算法
刘大猫263 小时前
Datax安装及基本使用
java·人工智能·算法