Leetcode2560. 打家劫舍 IV

2024-02-12 06:36

本文主要是介绍Leetcode2560. 打家劫舍 IV,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Every day a Leetcode

题目来源:2560. 打家劫舍 IV

解法1:二分答案 + 动态规划

给定数组 nums,从中选择一个长度至少为 k 的子序列 A,要求 A 中没有任何元素在 nums 中是相邻的。

最小化 max⁡(A)。

看到「最大化最小值」或者「最小化最大值」就要想到二分答案,这是一个固定的套路。

对于本题,「偷走的最大金额」越小,能偷的房子就越少,反之越多。

一般地,二分的值越小,越不能/能满足要求;二分的值越大,越能/不能满足要求。有单调性的保证,就可以二分答案了。

把二分中点 mid 记作 mx,定义 dp[i] 表示从 nums[0] 到 nums[i] 中偷金额不超过 mx 的房屋,最多能偷多少间房屋。如果 dp[n−1]≥k 则表示答案至多为 mx,否则表示答案必须超过 mx。

用「选或不选」来分类讨论:

  • 不选 nums[i]:dp[i]=dp[i−1];
  • 选 nums[i],前提是 nums[i]≤mx:dp[i]=dp[i−2]+1。

这两取最大值,即:dp[i]=max(dp[i−1],dp[i−2]+1)。

代码:

/** @lc app=leetcode.cn id=2560 lang=cpp** [2560] 打家劫舍 IV*/// @lc code=start// 二分答案 + 动态规划class Solution
{
public:int minCapability(vector<int> &nums, int k){int n = nums.size();int left = *min_element(nums.begin(), nums.end());int right = *max_element(nums.begin(), nums.end());// mx 是二分猜测的窃取能力auto check = [&](int mx, int k) -> bool{// dp[i]: 从 nums[0, i] 中偷金额不超过 mx 的房屋,最多能偷多少间房屋vector<long long> dp(n, 0);// 初始化dp[0] = nums[0] <= mx ? 1 : 0;if (dp[0] || nums[1] <= mx)dp[1] = 1;// 状态转移for (int i = 2; i < n; i++){if (nums[i] > mx)dp[i] = dp[i - 1];elsedp[i] = max(dp[i - 1], dp[i - 2] + 1);}return dp[n - 1] >= k;};while (left < right){int mid = left + (right - left) / 2;if (check(mid, k))right = mid;elseleft = mid + 1;}return left;}
};
// @lc code=end

结果:

在这里插入图片描述

复杂度分析:

时间复杂度:O(nlogU),其中 n 为数组 nums 的长度,U=max(nums)。

空间复杂度:O(n),其中 n 为数组 nums 的长度。

解法2:二分答案 + 贪心

也可以用贪心做。

考虑到只需要计算个数,在从左到右遍历的情况下只要当前房子可以偷,就立刻偷。

严格证明如下:

在这里插入图片描述

代码:

// 二分答案 + 贪心class Solution
{
public:int minCapability(vector<int> &nums, int k){int n = nums.size();int left = *min_element(nums.begin(), nums.end());int right = *max_element(nums.begin(), nums.end());// mx 是二分猜测的窃取能力auto check = [&](int mx, int k) -> bool{int count = 0;for (int i = 0; i < n; i++)if (nums[i] <= mx){count++;i++; // 跳过下一间房子}return count >= k;};while (left < right){int mid = left + (right - left) / 2;if (check(mid, k))right = mid;elseleft = mid + 1;}return left;}
};

结果:

在这里插入图片描述

复杂度分析:

时间复杂度:O(nlogU),其中 n 为数组 nums 的长度,U=max(nums)。

空间复杂度:O(1)。

这篇关于Leetcode2560. 打家劫舍 IV的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/701902

相关文章

动态规划---打家劫舍

题目: 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 思路: 动态规划五部曲: 1.确定dp数组及含义 dp数组是一维数组,dp[i]代表

每日一题,力扣leetcode Hot100之198.打家劫舍

这一道题乍一看可以双层循环暴力解,但是仔细一想有可能最大利益并不是一家隔着一家偷,我可以间隔很多家偷,所以 这个题的思路还是有点像爬楼梯,用动态规划解。 首先确立动态规划的初始条件: 1.dp[0]=nums[0]只有一家 2.dp[1]=max(nums[0],nums[1])有两家选一家多的 然后确立动态规划的循环条件: dp[i]应该是什么 1.第i家能拿,那么dp[i]=n

【python因果推断库7】使用 pymc 模型的工具变量建模 (IV)2

目录 与普通最小二乘法 (OLS) 的比较 应用理论:政治制度与GDP 拟合模型:贝叶斯方法  多变量结果和相关性度量 结论 与普通最小二乘法 (OLS) 的比较 simple_ols_reg = sk_lin_reg().fit(X.reshape(-1, 1), y)print("Intercept:", simple_ols_reg.intercept_, "Bet

【python因果推断库6】使用 pymc 模型的工具变量建模 (IV)1

目录 使用 pymc 模型的工具变量建模 (IV) 使用 pymc 模型的工具变量建模 (IV) 这份笔记展示了一个使用工具变量模型(Instrumental Variable, IV)的例子。我们将会遵循 Acemoglu, Johnson 和 Robinson (2001) 的一个案例研究,该研究尝试解开强大的政治机构对于以国内生产总值(GDP)衡量的经济生产力的影响。本示例借鉴

LeetCode讲解篇之213. 打家劫舍 II

文章目录 题目描述题解思路题解代码 题目描述 你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。 给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷

网络层 IV(ARP、DHCP、ICMP)【★★★★★★】

(★★)代表非常重要的知识点,(★)代表重要的知识点。 一、地址解析协议(ARP)(★★) 在局域网中,由于硬件地址已固化在网卡上的 ROM 中,因此常常将硬件地址称为物理地址。因为在局域网的 MAC 帧中的源地址和目的地址都是硬件地址,因此硬件地址又称为 MAC 地址。即物理地址、硬件地址和 MAC 地址常常作为同义词出现。 1. IP 地址与 MAC 地址 从层次的角度看,

Leetcode面试经典150题-188.买卖股票的最佳时机IV

解法都在代码里,不懂就留言或者私信,这个稍微难点,我提供了两种解法 /**基本的动态规划求解的过程 */public static int maxProfit2(int k, int[] prices) {/**题目给的数组不会为null,这里习惯性的健壮性判断如果交易日小于2,不可能获得任何的利润 */if(prices == null || prices.length < 2) {retu

leetcode198打家劫舍

打家劫舍 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 public int rob(int[] nums) {if(nums.length

代码随想录Day39:198.打家劫舍、213.打家劫舍II、337.打家劫舍III

198. 打家劫舍 题目链接:LeetCode198.打家劫舍 文档讲解:代码随想录LeetCode198.打家劫舍 题解 dp[i]偷或不偷,取决于dp[i-1]和dp[i-2]是否偷 class Solution {public:int rob(vector<int>& nums) {if (nums.size() == 1)return nums[0];vector<i

代码随想录算法训练营第三十九天 | 198.打家劫舍 , 213.打家劫舍II , 337.打家劫舍III

目录 198.打家劫舍 思路 1.确定dp数组(dp table)以及下标的含义 2.确定递推公式 3.dp数组如何初始化 4.确定遍历顺序 5.举例推导dp数组 方法一: 动态规划-一维 方法二:动态规划-二维 方法三:动态规划-两个变量 213.打家劫舍II 思路 方法一:动态规划- 方法二:动态规划-二维 方法三:动态规划-不封装函数  337.打家劫舍III