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;
    }
};
相关推荐
luckys.one3 小时前
第9篇:Freqtrade量化交易之config.json 基础入门与初始化
javascript·数据库·python·mysql·算法·json·区块链
~|Bernard|4 小时前
在 PyCharm 里怎么“点鼠标”完成指令同样的运行操作
算法·conda
战术摸鱼大师4 小时前
电机控制(四)-级联PID控制器与参数整定(MATLAB&Simulink)
算法·matlab·运动控制·电机控制
Christo34 小时前
TFS-2018《On the convergence of the sparse possibilistic c-means algorithm》
人工智能·算法·机器学习·数据挖掘
好家伙VCC5 小时前
数学建模模型 全网最全 数学建模常见算法汇总 含代码分析讲解
大数据·嵌入式硬件·算法·数学建模
liulilittle7 小时前
IP校验和算法:从网络协议到SIMD深度优化
网络·c++·网络协议·tcp/ip·算法·ip·通信
bkspiderx8 小时前
C++经典的数据结构与算法之经典算法思想:贪心算法(Greedy)
数据结构·c++·算法·贪心算法
中华小当家呐10 小时前
算法之常见八大排序
数据结构·算法·排序算法
沐怡旸10 小时前
【算法--链表】114.二叉树展开为链表--通俗讲解
算法·面试
一只懒洋洋11 小时前
K-meas 聚类、KNN算法、决策树、随机森林
算法·决策树·聚类