代码编织梦想

Problem_link: 213. 打家劫舍 II

前言

偷东西是不对的


思路

思路和打家劫舍普通差不多,只是多了一个头尾不能同时偷的条件,既然这样,就遍历两次,第一次不管第一家,第二次不管最后一家。


解题方法

  • 边界
    l e n ( n u m s ) < = 3 len(nums)<=3 len(nums)<=3时,只能选一家,所以挑最大的选就行了。代码是可以处理2家以上的情况的,这样直接返回略快一些。

  • 定义状态
    每家我们都有偷和不偷两种情况:
  1. 如果偷,它的前一家就不能偷,结果就等于前一家不偷的情况加上这家的金额。
  2. 如果不偷,结果就是前一家偷和前一家不偷两种情况中的最大值。
    所以, d p [ i ] [ 0   o r   1 ] dp[i][0\ or\ 1] dp[i][0 or 1]表示第i+1家(i从0开始)偷(1)和不偷(0)两种情况的最优解。
    { d p [ 0 ] [ 0 ] = 0 第一家不偷 d p [ 0 ] [ 1 ] = n u m s [ 0 ] 第一家偷 d p [ i ] [ 0 ] = m a x ( d p [ i − 1 ] [ 1 ] , d p [ i − 1 ] [ 0 ] ) 不偷这一家 d p [ i ] [ 1 ] = d p [ i − 1 ] [ 0 ] + n u m s [ i ] 偷这一家 \begin{cases} dp[0][0] = 0 & 第一家不偷 \\ dp[0][1] = nums[0]& 第一家偷 \\ dp[i][0] = max(dp[i-1][1],dp[i-1][0])& 不偷这一家 \\ dp[i][1] = dp[i-1][0]+nums[i] & 偷这一家 \end{cases} dp[0][0]=0dp[0][1]=nums[0]dp[i][0]=max(dp[i1][1],dp[i1][0])dp[i][1]=dp[i1][0]+nums[i]第一家不偷第一家偷不偷这一家偷这一家

  • 首尾问题
    遍历两次,让首尾不同时出现就可以解决。
  • 最终结果
    把两次遍历的结果都做最大值比较,结果就出来了。

复杂度

  • 时间复杂度:
    O ( n ) O(n) O(n)

  • 空间复杂度:
    O ( n ) O(n) O(n)

Code

int max(int a,int b){
    return a>b?a:b;
}
// 偷家范围
int robRange(int* nums, int start, int end) {
    // 对第i个房子偷和不偷,0是不偷,1是偷
    int dp[100][2] = {{0}};
    dp[start][0] = 0;
    dp[start][1] = nums[start];
    for (int i = start+1; i < end; i++) {
        dp[i][0] = max(dp[i-1][0],dp[i-1][1]);
        dp[i][1] = dp[i-1][0]+nums[i];
    }
    return max(dp[end-1][0],dp[end-1][1]);
}
int rob(int* nums, int numsSize){
    // 边界
    
    if(numsSize<=3){
        int res = nums[0];
        for(int i=1;i<numsSize;i++){
            res = max(res,nums[i]);
        }
        return res;
    }

    // 不管第一家的结果和不管最后一家的结果进行比较
    return max(robRange(nums,1,numsSize),robRange(nums,0,numsSize-1));
}

可以发现每次只使用上一次偷家状态,所以可以将空间优化为常量。


class Solution:
    def rob(self, nums: List[int]) -> int:
        # 边界
        if(len(nums)<=3):
            return max(nums)

        def robRange(nums: List[int],start,end) ->int:
            # 偷上一家
            stealFami   = nums[start]
            # 不偷上一家
            notstealFami= 0

            # 偷这一家
            notstealThisFami=None
            # 不偷这一家
            stealThisFami   =None
            for i in range(start+1,end):
                notstealThisFami = max(stealFami,notstealFami)
                stealThisFami   = notstealFami+nums[i]
                stealFami,notstealFami = stealThisFami,notstealThisFami
            return max(stealFami,notstealFami)

        return max(robRange(nums,1,len(nums)),robRange(nums,0,len(nums)-1))

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_63622800/article/details/129630392

第十四届蓝桥杯模拟赛(第三期)试题与题解 c++-爱代码爱编程

目录 一、填空题 (一)最小的十六进制(答案:2730) (二)Excel的列(答案:BYT) (三)相等日期(答案:70910) (四)多少种取法(答案:189) (五)最大连通分块(答案:148) 二、编程题 (一)哪一天 (二)信号覆盖 (三)清理水草 (四)最长滑行 (五)区间最小值 一、填空题 (一)最小的十六进

day7-列表作业2-爱代码爱编程

创建一个列表,列表中有10个数字, 保证列表中元素的顺序,对列表进行排重,并对列表使用进行降序排序 例如:[70, 88, 91, 70, 107, 234, 91, 177, 282, 197] --- 去重之后 [

推荐系统1-推荐系统简介-爱代码爱编程

目录标题 推荐系统简介1、推荐系统目的2、推荐系统的应用3、推荐系统的基本思想4、推荐系统的数据分析5、推荐系统的分类6、推荐算法简介6.1 基于人口统计学的推荐算法(基于用户数据)6.2 基于内容的推荐算法(基于内

动态顺序表(c语言实现)-爱代码爱编程

坚持学习 目录 1.顺序表的概念  2.顺序表的定义 3.顺序表的接口函数 3.1顺序表初始化 3.2检查顺序表是否需要扩容  3.3尾插数据  3.4尾删数据 3.5头插数据 3.6头删数据 3.7打印顺序表的数据 3.8销毁顺序表 3.9在指定位置插入数据 3.10删除指定位置的数据 3.11查找指定数据 4.

数据结构——【顺序表】基本操作代码-爱代码爱编程

先来讲解一下如何实现线性表: 1 .  基本构成框架是结构体,结构体内部由两个成员:一个是数组,一个是标记last(而这都是整型)。数组是用来记录数据,标记是用来表示最后一个元素的位置。 2 .  put函数:对标记进行初始化,也就是让last=-1,然后利用循环输入数据。 3 .  check函数:利用循环遍历并打印线性表。

codeforces 1042b vitamins-爱代码爱编程

Codeforces 1042B Vitamins 链接: https://codeforces.com/contest/1042/problem/B 题目描述 Berland shop sells n kinds o

《程序员面试金典(第6版)》面试题 04.10. 检查子树-爱代码爱编程

题目描述 检查子树。你有两棵非常大的二叉树:T1,有几万个节点;T2,有几万个节点。设计一个算法,判断 T2 是否为 T1 的子树。 如果 T1 有这么一个节点 n,其子树与 T2 一模一样,则 T2 为 T1 的子树,

csp202209-2 何以包邮?-爱代码爱编程

题目描述 新学期伊始,适逢顿顿书城有购书满 x 元包邮的活动,小 P 同学欣然前往准备买些参考书。 一番浏览后,小 P 初步筛选出 n 本书加入购物车中,其中第 i 本(1≤i≤n)的价格为 ai 元。 考虑到预算有限,在最终付款前小 P 决定再从购物车中删去几本书(也可以不删),使得剩余图书的价格总和 m 在满足包邮条件(m≥x)的前提下最小。

[牛客算法总结]:重建二叉树-爱代码爱编程

   标签: 二叉树、DFS、先序遍历、中序遍历、递归   题目: 给定节点数为 n 的二叉树的前序遍历和中序遍历结果,请重建出该二叉树并返回它的头结点。 例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中

寒假所学算法复习3月12总结-爱代码爱编程

3月12复习了深度优先搜索(dfs)和广度优先搜索(bfs) 刷了洛谷上的一道题:[POI2007]GRZ-Ridges and Valleys - 洛谷 原本想用dfs写,但写到一半,发现思路不对,于是又用bfs去写,思路如下: 地图上有三种区域,山峰,山谷,山坡,当一个相同数的区域的周围全是比这个数要小的数这个区域就是山峰,否则就是山谷,但

用javascript分类刷leetcode6.深度优先&广度优先(图文视频讲解)_javascript leetcode 6题-爱代码爱编程

深度优先&广度优先 动画过大,点击查看 bfs:适用于层序遍历或者寻找最短路径的问。 //bfs伪代码模版 function bfs(graph, start, end) { queue =

数字三角形-爱代码爱编程

目录 题目描述  解题思路 DP初始化 DP最终条件 DP初始条件 题目限制条件 总代码 题目描述  解题思路 首先映入我们眼帘的就是一个三角形,加求路径和最大,类似于找最短路径的题,很明显是一个二维数组的动态规划问题,对于动态规划问题我们只需要找好最终条件,初始条件(也就是特殊条件),当然还要题目限制的条件既可求解。

c++11中lambda新特性_c++11 中 lambda 新特性-爱代码爱编程

1.定义 lambda匿名函数的语法格式: [外部变量访问方式说明符](参数)mutablenoexcept/throw()->返回值类型 { 函数体; }; 其中各部分的含义分别为:

第十四届蓝桥杯第三期模拟赛 c/c++ b组 原题与详解_对于一个日期,我们可以计算出年份的各个数位上的数字之和,也可以分别计算月和日的-爱代码爱编程

1、找最小全为字母的16进制数。 2、求一个数的26进制并用A-Z字母表示 3、日期相等 4、乘积方案数 5、最大连通块 6、求星期几 7、范围覆盖点数 8、清理水草 9、滑行距离 10、序号最小值 1、找最小全为字母的16进制数。 请找到一个大于 2022 的最小数,这个数转换成十六进制之后,所有

一本通 2.9.2 动态规划中背包问题_一本通 背包问题-爱代码爱编程

1260:【例9.4】拦截导弹(Noip1999) 【题目描述】 一个旅行者有一个最多能装 M 公斤的背包,现在有 n�件物品,它们的重量分别是W1,W2,...,Wn,它们的价值分别为C1,C2,...,Cn,求旅行者能获得最大总价值。 【题目分析】  【代码实现】 #include <bits/stdc++.h> usi

occt_modeling_data(一)——拓扑_topods_shape topods_tshape-爱代码爱编程

下面是我基于opencascade英文文档中关于occt_modeling_data中Topology部分进行的翻译,英文好的还是建议直接看文档,部分我不肯定的地方我会附上英文原句。如发现有错误欢迎评论区留言。

三、javascript正则表达式_正则y模式-爱代码爱编程

文章目录 一、Javascript正则表达式1.1 y模式1.2 原子表的基本使用1.3 区间匹配1.4 认识原子组1.5 嵌套分组与不记录分组1.6 批量使用正则表达式完成密码验证1.7 禁止使用贪婪