【动态规划】简单多状态dp问题(1)打家劫舍问题

news2024/11/24 20:06:20

打家劫舍问题

在这里插入图片描述

文章目录

  • 【动态规划】简单多状态dp问题(1)打家劫舍问题
    • 1. 按摩师(打家劫舍Ⅰ)
      • 1.1 题目解析
      • 1.2 算法原理
        • 1.2.1 状态表示
        • 1.2.2 状态转移方程
        • 1.2.3 初始化
        • 1.2.4 填表顺序
        • 1.2.5 返回值
      • 1.3 编写代码
    • 2. 打家劫舍Ⅱ
      • 2.1 题目解析
      • 2.2 算法原理
        • 2.2.1 状态表示
        • 2.2.2 状态转移方程
        • 2.2.3 初始化
        • 2.2.4 填表顺序
        • 2.2.5 返回值
      • 2.3 编写代码
    • 3. 删除并获得点数
      • 3.1 题目解析
      • 3.2 算法原理
        • 3.2.1 状态表示
        • 3.2.2 状态转移方程
        • 3.2.3 初始化
        • 3.2.4 填表顺序
        • 3.2.5 返回值
      • 3.3 编写代码
    • 4. 粉刷房子
      • 4.1 题目解析
      • 4.2 算法原理
        • 4.2.1 状态表示
        • 4.2.2 状态转移方程
        • 4.2.3 初始化
        • 4.2.4 填表顺序
        • 4.2.5 返回值
      • 4.3 编写代码

【动态规划】简单多状态dp问题(1)打家劫舍问题

1. 按摩师(打家劫舍Ⅰ)

传送门:面试题 17.16. 按摩师

题目:

在这里插入图片描述

1.1 题目解析

在这里插入图片描述

越难的dp问题,看示例只能起到了解题目的效果,一般推不出啥普遍的规律,所以接下来就是我们的算法原理,通过动归的思想去理解,才会豁然开朗!

1.2 算法原理

1.2.1 状态表示

我们需要通过经验 + 题目要求去决定状态表示:

  1. 根据题目的意境以及数据结构,我们得出需要建立一维的dp表(大小为 n)
    • 对于为什么用一维,首先这道题数据结构为一维的,而一维如果确实可以解决问题就没有必要上升到二维
  2. 经验:以某个坐标为结尾或者以某个坐标为起点去研究题目问题!
    • 此题用的是“结尾”

再根据经验,一般dp表的其中一值就应该是答案!

  • 所以含义应该就是“最长预约时长”

综合得到状态表示:dp[i]表示就是起点到坐标为 i 的位置这些天以来的最长预约时长

而这道题,与之前做过的题不一样的是,一个坐标的状态有两种情况,需要我们继续细化

  1. 接单
  2. 不接单

在之前的题目里,我们到达一个坐标并无其他选择,而现在有~

  • 而我们需要有两个dp表来细化表示这两个状态,因为一个dp表是无法表示这两种状态的,这就是简单的多状态dp问题的关键!

在这里插入图片描述

  • 其中 f 和 g 对应中学阶段的函数 f 和函数 g 的这种常用的写法
  • 当然也可以写成二维数组(n × 2)

所以,最终的状态表示为:

f[i]表示的是,从起点到 i 坐标的这些天内,i这一天接单的情况下的最长预约时间

g[i]表示的是,从起点到 i 坐标的这些天内,i这一天不接单的情况下的最长预约时间

1.2.2 状态转移方程

同样的套路,我们需要根据已确定的dp表的值来推导 f[i] 和 g[i] 的值,并且牢记他们的状态表示!

  1. 我们以坐标 i 为结尾
  2. 根据“最近一步”去划分问题

“最近一步”可以理解为“必然事件”

  • 此题的“必然事件”就是,到达坐标 i 之前,必然要先到达坐标 i - 1

在这里插入图片描述

  1. 这一天如果接单的话,那么前一天就必须不接单,那么预约时长为今天的预约时长nums[i]加上,上一天的不接单情况下的最长预约时长g[i - 1]
  2. 这一天如果不接单的话,那么前一天可以接单,也可以不接单,那么预约时长则是,前一天接单情况和不接单情况的最长预约时长中的较大值

而1代表着f表怎么填,2代表着g表怎么填

所以得出状态转移方程:

f[i] = nums[i] + g[i - 1];

g[i] = max{f[i - 1], g[i - 1]};

1.2.3 初始化

这道题可以用假数据的方法,但是没有必要,因为我们只需要初始化第一个值就行了~

  1. 如果第一天接单,则预约时长就是nums[0]
  2. 如果第一天不接单,则预约时长就是0

1.2.4 填表顺序

从左往右两个表一起填

在这里插入图片描述

1.2.5 返回值

返回的就是起点到终点,即所有天以来的最长预约时长,即f[n - 1]或者g[n - 1]

  • 最后一天两种可能都有,所以返回其较大值!

1.3 编写代码

  • 根据算法原理编写代码即可:
  1. 创建dp表
  2. 初始化,处理边界问题
  3. 填表
  4. 返回值
class Solution {
    public int massage(int[] nums) {
        //1. 创建dp表
        //2. 初始化
        //3. 填表
        //4. 返回值
        int n = nums.length;
        if(n == 0) {
            return 0;
        }
        int[] f = new int[n];
        int[] g = new int[n];
        f[0] = nums[0];
        for(int i = 1; i < n; i++) {
            f[i] = nums[i] + g[i - 1];
            g[i] = Math.max(f[i - 1], g[i - 1]);
        }
        return Math.max(f[n - 1], g[n - 1]);  
    }
}

时空复杂度都为:O(N)

在这里插入图片描述

2. 打家劫舍Ⅱ

传送门:力扣213. 打家劫舍 II

题目:

在这里插入图片描述

2.1 题目解析

在这里插入图片描述

在这里插入图片描述

越难的dp问题,看示例只能起到了解题目的效果,一般推不出啥普遍的规律,所以接下来就是我们的算法原理,通过动归的思想去理解,才会豁然开朗!

2.2 算法原理

算法原理基本跟上一道题一致,只不过这一次成环了~

而并不想在状态转移方程中去判断这种情况,因为这是不现实的,因为f 表和g 表到达n - 2下标的时候,我们并不能确定n - 2坐标对应的情况,起点是否“偷”与“不偷”,并且我们也不能人为规定(影响最终结果)

  • 而我们也不能以环型的形式去创建dp表!

所以我们需要一个**预处理**的阶段:(往已知的解法靠拢,化未知为已知)

我们细化第一天的状态:(重点理解)

  1. 偷,则次日和最后一天不能偷,相当于对[2, n - 2]进行一次打家劫舍,最终结果加上nums[0]
  2. 不偷,则最后一天无所谓,相当于对[1, n - 1]进行一次打家劫舍
    在这里插入图片描述

而我们则需要去封装,“一次打家劫舍”的方法!

2.2.1 状态表示

我们需要通过经验 + 题目要求去决定状态表示:

  1. 根据题目的意境以及数据结构,我们得出需要建立一维的dp表(大小为 不一定,由传入的范围决定)
    • 本题有n-2大小,n-1大小
  2. 经验:以某个坐标为结尾或者以某个坐标为起点去研究题目问题!
    • 此题用的是“结尾”

再根据经验,一般dp表的其中一值就应该是答案!

  • 所以含义应该就是“最长预约时长”

综合得到状态表示:dp[i]表示就是起点到坐标为 i 的位置偷到的最大钱数

而这道题,与之前做过的题不一样的是,一个坐标的状态有两种情况,需要我们继续细化

  1. 不偷

在这里插入图片描述

所以,最终的状态表示为:

f[i]表示的是,从起点到 i 坐标的这些房间,i这个房间偷的情况下的最大钱数

g[i]表示的是,从起点到 i 坐标的这些房间,i这个房间不偷的情况下的最大钱数

2.2.2 状态转移方程

同样的套路,我们需要根据已确定的dp表的值来推导 f[i] 和 g[i] 的值,并且牢记他们的状态表示!

  1. 我们以坐标 i 为结尾
  2. 根据“最近一步”去划分问题

“最近一步”可以理解为“必然事件”

  • 此题的“必然事件”就是,到达坐标 i 之前,必然要先到达坐标 i - 1

在这里插入图片描述

  1. 这个房间如果偷的话,那么前一房间就必须不偷,那么金额为今天的钱额nums[i]加上,上一个房间的不偷情况下的最大金额g[i - 1]
  2. 这个房间如果不偷的话,那么前一个房间可以偷,也可以不偷,那么最大金额则是,前一个房间的偷情况和不偷情况的最大金额中的较大值

而1代表着f表怎么填,2代表着g表怎么填

所以得出状态转移方程:

f[i] = nums[i] + g[i - 1];

g[i] = max{f[i - 1], g[i - 1]};

2.2.3 初始化

本题由于要两次建表,而两次建表的填表起始点和终点都不一样
在这里插入图片描述

  1. 第一个房间偷:
    1. f[2] = nums[2]
    2. g[2] = 0
  2. 第一个房间偷:
    1. f[1] = nums[1]
    2. g[2]

2.2.4 填表顺序

从左往右两个表一起填

  1. 第一个房间偷:从2开始填到n - 2
  2. 第二个房间偷:从1开始填到n - 1

在这里插入图片描述

2.2.5 返回值

  1. 第一个房间偷:最大值应该为f[n - 2]和g[n - 2]的较大值,再加上nums[0]
  2. 第一个房间偷:最大值应该为f[n - 1]和g[n - 2]的较大值

2.3 编写代码

一次打家劫舍操作的方法封装:

  • 由于要与nums对应,所以我选择不限制dp表的大小,而是限制填表范围!
public int oneRob(int[] nums, int left, int right) {
    int n = nums.length;
    int[] f = new int[n];
    int[] g = new int[n];
    f[left] = nums[left];
    for(int i = left + 1; i <= right; i++) {
        f[i] = nums[i] + g[i - 1];
        g[i] = Math.max(f[i - 1], g[i - 1]);
    }
    return Math.max(f[right], g[right]);
}

核心方法:

  • 对于元素太少的边界情况要提前处理!
class Solution {
    public int rob(int[] nums) {
        int n = nums.length;
        if(n == 1) {
            return nums[0];
        }
        if(n == 2) {
            return Math.max(nums[0], nums[1]);
        }
        int yes = nums[0] + oneRob(nums, 2, n - 2);
        int no = oneRob(nums, 1, n - 1);
        return Math.max(yes, no);
    }
}
  • 注意下标对应!

时空复杂度都为:O(N)
在这里插入图片描述

3. 删除并获得点数

传送门:力扣740. 删除并获得点数

题目:

在这里插入图片描述

3.1 题目解析

在这里插入图片描述

在这里插入图片描述

越难的dp问题,看示例只能起到了解题目的效果,一般推不出啥普遍的规律,所以接下来就是我们的算法原理,通过动归的思想去理解,才会豁然开朗!

3.2 算法原理

首先,我们需要将这些数据进行一个排序,这是很容易想到的,这样可以很好的观察到数据的发布情况(值为x的数的个数也明显)

在这里插入图片描述

而这样也不够,我们怎么往动态规划的方向去靠拢呢

  • 现在还不能创建出dp表,因为如果按照nums的大小创建的话,那么下标对应的元素的状态也是不好确定的,例如:
    1. 值相同的元素含义相同?
    2. x-1和x-2不一定存在,且无法确认其下标

所以很快就能想到以下操作:

  • 相同的元素“融合起来”
    在这里插入图片描述

  • 值与下标有关(哈希思想):

    • 顺手解决如何找到x-1和x+1的问题
      在这里插入图片描述
  • 对于不存在的值,默认对应值为0
    在这里插入图片描述

猛地一看!

  • 是不是就是打家劫舍问题!

问题:这样岂不是会选到不存在的数字?

  • 对,但是没有关系,因为选择到不存在的数字,最终结果的情况中,不可能选择到不存在的数,因为这道题,nums元素都大于等于1,所以选择到不存在数字的时候,就相当于获得点数为0,反而导致我们不能选择一些高点数的东西
    1. 相当于不选
    2. 相当于自找苦头
  • 所以在此情况下,选择不存在的数是自找苦吃的!
  • 而如果nums元素的值没有正负限制,那么也没关系,因为选择这个不存在的数字,一样不会促进后续去获得点数,因为我们“不限制其选择不存在的数字”的情景下,他的最优解本来就可以不选那些大的负数即可,不需要靠选择不存在的数字来限制其不能选

即,不限制其选择不存在的数字,是完全考虑选择在不存在数字的情况下的强大的最优解

3.2.1 状态表示

我们需要通过经验 + 题目要求去决定状态表示:

  1. 根据题目的意境以及数据结构,我们得出需要建立一维的dp表(大小为输入案例nums数组的最大值 + 1,即**1e4 + 1**:科学计数法)
    • 因为1e4也要对应到1e4下标
  2. 经验:以某个坐标为结尾或者以某个坐标为起点去研究题目问题!
    • 此题用的是“结尾”

再根据经验,一般dp表的其中一值就应该是答案!

  • 所以含义应该就是“最大点数”

综合得到状态表示:dp[i]表示就是起点到坐标为 i 的位置能获得的最大点数

而这道题,与之前做过的题不一样的是,一个坐标的状态有两种情况,需要我们继续细化

  1. 不选
    在这里插入图片描述

所以,最终的状态表示为:

f[i]表示的是,从起点到 i 坐标的这些数内,i这一个数不选情况下能获得的最大点数

g[i]表示的是,从起点到 i 坐标的这些数内,i这一个数不选的情况下能获得的最大点数

3.2.2 状态转移方程

同样的套路,我们需要根据已确定的dp表的值来推导 f[i] 和 g[i] 的值,并且牢记他们的状态表示!

  1. 我们以坐标 i 为结尾
  2. 根据“最近一步”去划分问题

“最近一步”可以理解为“必然事件”

  • 此题的“必然事件”就是,到达坐标 i 之前,必然要先到达坐标 i - 1
    在这里插入图片描述
  1. 这个数如果选的话,那么x - 1就必须不选,那么获得点数为统计数组arr[i]加上,上一天的不选的情况下的能获得的最大点数g[i - 1]
  2. 这个数如果不选的话,那么前一天可以选,也可以不选,那么获得的点数则是,前一天选情况和不选情况的最大点数中的较大值

而1代表着f表怎么填,2代表着g表怎么填

所以得出状态转移方程:

f[i] = arr[i] + g[i - 1];

g[i] = max{f[i - 1], g[i - 1]};

3.2.3 初始化

0这个数是不存在的树,所以选和不选f[0]和g[0]都为0

3.2.4 填表顺序

从左往右两个表一起填

3.2.5 返回值

f[1e4] 和 g[1e4]的较大值

3.3 编写代码

  1. 预处理

  2. 创建dp表

  3. 填表

  4. 返回值

class Solution {
    public int deleteAndEarn(int[] nums) {
        //1. 预处理
        int max = (int)1e4;
        int[] arr = new int[max + 1];
        for(int i = 0; i < nums.length; i++) {
            int index = nums[i];
            arr[index] += index;
        }
        //2. 创建dp表
        //3. 填表
        //4. 返回值
        int[] f = new int[max + 1];
        int[] g = new int[max + 1];
        for(int i = 1; i < max + 1; i++) {
            f[i] = arr[i] + g[i - 1];
            g[i] = Math.max(f[i - 1], g[i - 1]);
        }
        return Math.max(f[max], g[max]);
    }
}

时空复杂度都为:O(N)

在这里插入图片描述

4. 粉刷房子

传送门:力扣剑指 Offer II 091. 粉刷房子

题目:

在这里插入图片描述

4.1 题目解析

在这里插入图片描述

在这里插入图片描述

越难的dp问题,看示例只能起到了解题目的效果,一般推不出啥普遍的规律,所以接下来就是我们的算法原理,通过动归的思想去理解,才会豁然开朗!

4.2 算法原理

4.2.1 状态表示

我们需要通过经验 + 题目要求去决定状态表示:

  1. 根据题目的意境以及数据结构,我们得出需要建立二维的dp表(n × 3)
    • 也可以三个一维dp表,只不过在这里为了与costs表对应

在这里插入图片描述

  1. 经验:以某个坐标为结尾或者以某个坐标为起点去研究题目问题!
  • 此题用的是“结尾”

再根据经验,一般dp表的其中一值就应该是答案!

  • 所以含义应该就是“最大点数”

综合得到状态表示:dp[i]表示就是起点到坐标为 i 的位置时的这些房子粉刷完的最小花费

而这道题,与之前做过的题不一样的是,一个坐标的状态有三种情况,需要我们继续细化

  1. 绿
    在这里插入图片描述

所以,最终的状态表示为:

dp[i] [0]表示的是,从起点到 i 坐标的这些房子内,i这一个房子为红色情况下的最小花费

dp[i] [1]表示的是,从起点到 i 坐标的这些房子内,i这一个房子为蓝色情况下的最小花费

dp[i] [2]表示的是,从起点到 i 坐标的这些房子内,i这一个房子为绿色情况下的最小花费

4.2.2 状态转移方程

同样的套路,我们需要根据已确定的dp表的值来推导 f[i] 和 g[i] 的值,并且牢记他们的状态表示!

  1. 我们以坐标 i 为结尾
  2. 根据“最近一步”去划分问题

“最近一步”可以理解为“必然事件”

  • 此题的“必然事件”就是,到达坐标 i 之前,必然要先到达坐标 i - 1
    在这里插入图片描述
  1. 这个房子如果刷红色的话,那么前一个房子只能是蓝色或者绿色,即花费为dp[i] [1]和dp[i] [2]的较小值加上第i个房子刷红色费用costs[i] [0]
  2. 这个房子如果刷蓝色的话,那么前一个房子只能是红色或者绿色,即花费为dp[i] [0]和dp[i] [2]的较小值加上第i个房子刷蓝色费用costs[i] [0]
  3. 这个房子如果刷绿色的话,那么前一个房子只能是红色或者蓝色,即花费为dp[i] [0]和dp[i] [1]的较小值加上第i个房子刷绿色费用costs[i] [0]

而1代表着dp[i] [0]表怎么填,2代表着dp[i] [1]表怎么填,3代表着dp[i] [2]表怎么填

所以得出状态转移方程:

dp[i][0] = min{dp[i][1], dp[i][2]} + costs[i][0];

dp[i][1] = min{dp[i][0], dp[i][2]} + costs[i][1];

dp[i][2] = min{dp[i][0], dp[i][1]} + costs[i][2];

4.2.3 初始化

dp[0] [j] = costs[0] [j];

  • 第一个房间花费就是刷对应墙的花费~

4.2.4 填表顺序

从上到下,三列同时填
在这里插入图片描述

4.2.5 返回值

最后一个房间刷红刷蓝刷绿三种情况中的较小值~

4.3 编写代码

class Solution {
    public int minCost(int[][] costs) {
        //1. 创建dp表
        //2. 初始化
        //3. 填表
        //4. 返回值
        int n = costs.length;
        int[][] dp = new int[n][3];
        for(int i = 0; i < 3; i++) {
            dp[0][i] = costs[0][i];
        }
        for(int i = 1; i < n; i++) {
            dp[i][0] = costs[i][0] + Math.min(dp[i - 1][1], dp[i - 1][2]);
            dp[i][1] = costs[i][1] + Math.min(dp[i - 1][0], dp[i - 1][2]);
            dp[i][2] = costs[i][2] + Math.min(dp[i - 1][0], dp[i - 1][1]);
        }
        return Math.min(dp[n - 1][0], Math.min(dp[n - 1][1], dp[n - 1][2]));
    }
}

时空复杂度都为:O(N)

在这里插入图片描述

由于此类问题题目较多,分两篇文章讲述,下一篇文章的题目链接(买卖股票问题):

传送门:力扣309. 最佳买卖股票时机含冷冻期

传送门:力扣714. 买卖股票的最佳时机含手续费

传送门:力扣123.买卖股票的最佳时机 III

传送门:力扣188. 买卖股票的最佳时机 IV


文章到此结束!谢谢观看
可以叫我 小马,我可能写的不好或者有错误,但是一起加油鸭🦆

本文代码链接:动态规划03/src/Main.java · 游离态/马拉圈2023年6月 - 码云 - 开源中国 (gitee.com)


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/663306.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

seaborn笔记:heatmap

绘制热力图 1 基本使用方法 seaborn.heatmap(data, *, vminNone, vmaxNone, cmapNone, centerNone, robustFalse, annotNone, fmt.2g, annot_kwsNone, linewidths0, linecolorwhite, cbarTrue, cbar_kwsNone, cbar_axNone, squareFalse, xticklabelsauto, yticklabelsauto, m…

C++ 教程(16)——字符串

C 字符串 C 提供了以下两种类型的字符串表示形式&#xff1a; C 风格字符串C 引入的 string 类类型 C 风格字符串 C 风格的字符串起源于 C 语言&#xff0c;并在 C 中继续得到支持。字符串实际上是使用 null 字符 \0 终止的一维字符数组。因此&#xff0c;一个以 null 结尾…

Mysql的学习笔记

目录 1、rc 级别的 mvcc 和 rr 级别的mvcc 有啥区别&#xff1f; 2、Innodb与MyIsam的文件结构&#xff1f; 3、Innodb 与MyIsam的简单对比&#xff1f; 4、innodb&#xff0c;Alter table 改字段类型&#xff0c;底层会经历什么过程&#xff1f; 5、Alter table 改字段类型…

Zebec Protocol 与 PGP 深度合作,将流支付更广泛的应用薪资支付领域

随着传统机构的入局&#xff0c;以及相关加密合规法规的落地&#xff0c;加密支付正在成为一种备受欢迎的全新支付方式。加密支付基于区块链底层&#xff0c;不受地域、时间等的限制&#xff0c;能够实时到账&#xff0c;具备去中心化、非许可等特性。 流支付是一种具备创新性的…

Jmeter和Postman做接口测试的区别你知道吗

区别1:用例组织方式 不同的目录结构与组织方式代表不同工具的测试思想&#xff0c;学习一个测试工具应该首先了解其组织方式。 Jmeter的组织方式相对比较扁平&#xff0c;它首先没有WorkSpace&#xff08;工作空间&#xff09;的概念&#xff0c;直接是TestPlan&#xff08;测…

搜索旋转排序数组(leetcode 33)

文章目录 1.问题描述2.难度等级3.热门指数4.解题思路思路复杂度分析 5.实现示例参考文献 1.问题描述 整数数组按升序排列&#xff0c;数组中的值互不相同 。 假设数组在预先未知的某个点上进行了旋转。 如数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2]。 搜索一个给定的目…

如何安装Nginx服务

目录 一、Nginx服务 Nginx的并发能力受影响因素 二、Nginx与Apache的差异 Nginx相对于Apache的优点 Apache相对于Nginx的优点 三、阻塞/非阻塞 四、同步/异步 Nginx应用场景 五、编译安装Nginx服务 关闭防火墙和安全机制 安装依赖环境 将相关包导入/opt当中 进入指…

Linux分区的基本概念。

文章目录 前言 一、分区概念 1&#xff0c;书名&#xff0c;主引导纪录&#xff08;&#xff2d;&#xff22;&#xff32;&#xff09; 2&#xff0c;正文&#xff0c;就是硬盘中纪录的数据。 3&#xff0c;索引相当于硬盘中的分区表 3.1主分区&#xff08;存放地址&#xff0…

React、Vue项目build打包编译后如何再修改后台请求地址

vue项目大家都了解&#xff0c;开发用 npm run dev/npm run serve。而要上线则必须是先将项目打包编译 npm run build 之后成为了普通的静态网页才可上线进行部署及发布。同样这时候我们也已经将代码全部写好了。如果说要改里面的某个值或者修改请求地址我们应该怎么办呢&#…

IDEA中创建编写JSP

一、安装Tmocat并配置环境 安装请参考&#xff1a;https://www.cnblogs.com/weixinyu98/p/9822048.html 安装请参考&#xff1a;https://www.cnblogs.com/zhanlifeng/p/14917777.html 注意&#xff1a;在安装成功Tomcat测试是否成功安装时&#xff0c;访问“http://localhost:8…

selenium自动化教程及使用java来爬取数据

目录 一、介绍二、下载浏览器驱动1.获取要下载的驱动版本号2.下载驱动 三、Maven如下四、简单使用五、定位器1.定位器2.说明(1) class name 定位器(2) css selector 定位器(3) id 定位器(4) name 定位器(5) link text 定位器(6) partial link text 定位器(7) tag 定位器(8) xpa…

Android 内存检测LeakCanary

在github上下载了一个项目&#xff1a;安装debug版本会产生两个apk&#xff0c;一个是apk本身&#xff0c;一个是Leaks release版本就正常 不会产生这个问题&#xff0c;百思不得其解&#xff0c;第一次遇到这个问题。 看到这篇博客豁然开朗&#xff1a;在build.gradle.kts 里…

3天爆肝整理,性能测试问题汇总+解决办法(重要)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 开始性能测试前需…

入门孪生网络3-------使用一维卷积神经网络1DCNN与孪生网络的组合模型来实现excel数据的分类

文章目录 前言入门孪生网络的第三小节&#xff0c;我尝试使用keras或tensorflow2框架来搭建一个数据分类的网络。大家可以参考的程序思路&#xff0c;我也是小白&#xff0c;可以评论区一起讨论。 一、孪生网络与1DCNN组合网络的搭建思路二、我编写的孪生网络与1DCNN组合网络程…

操作教程:EasyCVR视频融合平台如何配置平台级联?

EasyCVR视频融合平台基于云边端一体化架构&#xff0c;可支持多协议、多类型设备接入&#xff0c;在视频能力上&#xff0c;平台可实现视频直播、录像、回放、检索、云存储、告警上报、语音对讲、电子地图、集群、智能分析以及平台级联等。平台可拓展性强、开放度高、部署轻快&…

干货讲解,财务报表结构分析

财务报表的构成是对企业财务状况、经营成果和现金流量的结构性表述。企业必须重视财务结构对经营业绩的影响&#xff0c;才能解决发展中的问题。 资产质量关注两个角度&#xff0c;一是资产结构&#xff0c;二是现金含量。 资产结构是什么意思呢&#xff1f;就是固定资产和无…

Linux 定时任务提权

Linux 定时任务提权 1.概述2.定时任务创建3.提权步骤 1.概述 定时任务&#xff08;cron job&#xff09;是Linux系统中的一个守护进程&#xff0c;用于调度重复任务&#xff0c;通过配置crontab可以让系统周期性地执行某些命令或者脚本。cron 是 Linux 系统中最为实用的工具之…

apple pencil二代平替笔哪个好用?苹果平板触控笔

随着互联网的快速发展&#xff0c;移动数码产品如手机、平板电脑、笔记本等正逐步进入人们的日常生活。同时电容笔的出现&#xff0c;也让这些产品的功能作用更上一层楼。由于苹果原装电容笔的价格非常贵&#xff0c;使得国内出现了越来越多的平替电容笔。总的来说&#xff0c;…

前端开发:基于cypress的自动化实践

如何在vue中使用cypress如何运行cypress如何编写测试用例如何解决测试数据的问题遇到的元素定位的问题如何看待cypresscypress是否为最佳工具测试怎么办&#xff1f; 如何在vue中使用cypress vue提供了vue-cli 可以快速的创建vue项目。 vue create hello-world在选择安装项里…

【亲测】集群环境中MMDetection3.0环境配置

本文记录下在集群环境下使用MMDetection的内容。 环境简介&#xff1a;所用集群设备为本地集群&#xff0c;具有管理节点和计算节点&#xff0c;且管理和计算在不同的主机上&#xff0c;作为用户&#xff0c;没有超级管理员权限。 MMdetection源码下载点击进入 这里主要记录下环…