[动态规划]---part1

news2024/11/17 5:37:07

前言

作者:小蜗牛向前冲

专栏小蜗牛算法之路

 专栏介绍"蜗牛之道,攀登大厂高峰,让我们携手学习算法。在这个专栏中,将涵盖动态规划、贪心算法、回溯等高阶技巧,不定期为你奉上基础数据结构的精彩算法之旅。一同努力,追逐技术的星辰大海。"

 

目录

 一、什么是动态规划

1、什么是动态规划

2、动态规划的学习

二、动态规划刷题

1、第 N 个泰波那契数

a、解题思路:

b、代码 

2、   面试题 08.01. 三步问题

 a、解题思路:

b、代码

3 、746. 使用最小花费爬楼梯

a、解题思路 

b、代码

  4、解码方法

a、解题思路 

b、代码

c、代码优化 

 5、不同路径(medium)

a、解题思路 

b、代码


本期我们将探讨动态规划,并提供5道经典动态规划问题,难度由浅入深。

 一、什么是动态规划

1、什么是动态规划

在学习算法的过程中,我们往往会遇到一些算法题是要用动态规划来解决。

但是做为小白的我们哪里知道动态规划是什么?

从概念上说

动态规划(Dynamic Programming)是一种解决复杂问题的算法设计技术。它通常用于解决具有重叠子问题和最优子结构性质的问题通过将问题分解为更小的子问题,并利用子问题的解来构建原始问题的解。

看完概念我们知道什么是动态规划,求重叠类子问题的 一般会用到动态规划的思路。

那我们如何求学习动态规划

2、动态规划的学习

对于算法类题目,在我们掌握算法的基本原理后,就是进行大量刷题,进经验的总结。

求解动态规划的五步骤:


1、状态表示


 在求解过程中,我们往往要创建dp表(其实就是数组),状态表示就是我们要找出dp表中值的含义是什么。

状态表 怎么来?

  • 根据题目要求
  • 经验+题目要求
  • 分析题目的过程中,发现重复子问题

 2、状态转移方程


 简单说是和dp[i]有关的一个方程


 3、初始化


保证在填写dp表的时候不越界


4、填写顺序 


 根据前面的计算得来,可以从前往后,也可以从后往前


 5、返回值

根据题目要求+状态表示

 讲完了解题步骤,下面就进行刷题训练。

特别提醒:后面博客会带领大家由易到难进行刷题,每期都为五题。

二、动态规划刷题

1、第 N 个泰波那契数

泰波那契序列 Tn 定义如下: 

T0 = 0, T1 = 1, T2 = 1, 且在 n >= 0 的条件下 Tn+3 = Tn + Tn+1 + Tn+2

给你整数 n,请返回第 n 个泰波那契数 Tn 的值。

示例 1:

输入:n = 4
输出:4
解释:
T_3 = 0 + 1 + 1 = 2
T_4 = 1 + 1 + 2 = 4

示例 2:

输入:n = 25
输出:1389537

提示:

  • 0 <= n <= 37
  • 答案保证是一个 32 位整数,即 answer <= 2^31 - 1

a、解题思路:

1、题目中的状态表示是什么?

 dp[i] 表⽰:第 i 个泰波那契数的值。

2、状态转移方程

由题目意很很容易知道是T(n) = T(n-1)+T(n-2)+T(n-3)

3、初始化dp表

为了防止数组越界我们只需要初始化:

dp[0]=0;

dp[1]=1;

dp[2]=1;

4、 填表顺序

由状态方程+题意知道从左往右填写到N

5、返回值

根据题目要求和dp[i]就为dp[n]

b、代码 

class Solution {
public:
    int tribonacci(int n) 
    {
        //动态规划
        //1.创建dp表
        //2.初始化表
        //3.填表
        //4.返回值

        //处理边界情况
        if(n==0)return 0;
        if(n==1||n==2)return 1;

        //1、创建dp表
        vector<int> dp(n+1);
        //2、初始化表
        dp[0]=0,dp[1]=1,dp[2]=1;
        //3、填表
        for(int i = 3;i<=n;i++)
        {
            dp[i] = dp[i-1]+dp[i-2]+dp[i-3];
        }
        //4、返回
        return dp[n];

    }
};

Leetcode 测试结果: 

2、   面试题 08.01. 三步问题

三步问题。有个小孩正在上楼梯,楼梯有n阶台阶,小孩一次可以上1阶、2阶或3阶。实现一种方法,计算小孩有多少种上楼梯的方式。结果可能很大,你需要对结果模1000000007。

示例1:

 输入:n = 3 
 输出:4
 说明: 有四种走法

示例2:

 输入:n = 5
 输出:13

提示:

  1. n范围在[1, 1000000]之间

 a、解题思路:

从0位置开始跳,下面我们来思考一下题意:

 ----->(表示跳台阶)

n=1时候

从0----->1 

走法为1


n=2时候

从0----->2

或者说我们让1----->2因为从 0----->1的走法我们已经考虑过了

走法为2


n=3时候

从0----->3或者说

我们让1----->3因为从 0----->1的走法我们已经考虑过了走法为1

也可以2----->3因为从 0----->2的走法我们已经考虑过了走法为2

走法为1+1+2=4


n=4时候

不管怎么说先走到1,在从1----->4走法为1

不管怎么说先走到2,在从2----->4走法为2

不管怎么说先走到3,在从3----->4走法为4

总共走法:1+2+4=7

大家这里是不是已经思路清晰起来了 

1、转态表示

以i位置为结尾,正好是到达第N个台阶,所以我们认为:

dp[i]表示:到达i位置时,一共有多少方法。

 2、状态转移方程

以i位置的状态,最近进的一步进行划分

从(i-1)--->i   dp[i-1]种走法

从(i-2)--->i   dp[i-2]种走法

从(i-3)--->i   dp[i-3]种走法

所以状态方程为:dp[i]=dp[i-1]+dp[i-2]+dp[i-3] ;

3、初始化

这里我们注意我们用不到i==0,因为0台阶的研究没有意义。

  dp[1] = 1, dp[2] = 2, dp[3] = 4;

4、 填表顺序

根据前面的推断肯定是从左往右。

5、返回值

根据题目要求和dp[i]就为dp[n]

b、代码

这题虽然和第一题非常相似但是有细节要处理、

class Solution {
public:
    //取模
    const int MOD = 1e9 + 7;
    int waysToStep(int n)
    {
        //处理边界情况:
        if (n == 1 || n == 2)return n;
        if (n == 3)return 4;

        //创建dp表
        vector<int> dp(n + 1);

        //初始化
        dp[1] = 1, dp[2] = 2, dp[3] = 4;

        //填表
        for (int i = 4; i <= n; i++)
        {
            //结果可能很大要进去取模
            dp[i] = ((dp[i - 1] + dp[i - 2]) % MOD + dp[i - 3]) % MOD;
        }
        //返回
        return dp[n];
    }
};

Leetcode 测试结果: 

3 、746. 使用最小花费爬楼梯

给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。

你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。

请你计算并返回达到楼梯顶部的最低花费。

示例 1:

输入:cost = [10,15,20]
输出:15
解释:你将从下标为 1 的台阶开始。
- 支付 15 ,向上爬两个台阶,到达楼梯顶部。
总花费为 15 。

示例 2:

输入:cost = [1,100,1,1,1,100,1,1,100,1]
输出:6
解释:你将从下标为 0 的台阶开始。
- 支付 1 ,向上爬两个台阶,到达下标为 2 的台阶。
- 支付 1 ,向上爬两个台阶,到达下标为 4 的台阶。
- 支付 1 ,向上爬两个台阶,到达下标为 6 的台阶。
- 支付 1 ,向上爬一个台阶,到达下标为 7 的台阶。
- 支付 1 ,向上爬两个台阶,到达下标为 9 的台阶。
- 支付 1 ,向上爬一个台阶,到达楼梯顶部。
总花费为 6 。

提示:

  • 2 <= cost.length <= 1000
  • 0 <= cost[i] <= 999

a、解题思路 

这里我们要注意到达楼顶,应该是const数组最后一个位置的下一个位置

这里我们有二种思路:

思路一:

1、转态表示

以i位置为结尾,正好是楼顶,所以我们认为:

dp[i]表示:到达i位置时,最小花费

 2、状态转移方程

根据最近的一个位置划分

先到达i-1的位置,然后支付const[i-1],走一步, 花费:dp[i-1]+cost[i-1]

先到达i-2的位置,然后支付const[i-2],走一步, 花费:dp[i-2]+cost[i-2]

所以dp[i] =min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);

3、初始化

保证dp表不越界就好dp[0]=dp[1]=0;

4、 填表顺序

从左往右

5、返回值

dp[n]


思路2:

1、转态表示

以i位置为起点,到达楼顶,所以我们认为:

dp[i]表示:从i位置出发到达楼顶,此时最小花费

 2、状态转移方程

根据最近的一个位置划分

  • 支付const[i],往后走一步, 从i+1位置出发到楼顶,花费:dp[i+1]+cost[i]
  • 支付const[i],往后走二步, 从i+2位置出发到楼顶,花费:dp[i+2]+cost[i]

所以dp[i] =min(dp[i+1]+cost[i],dp[i+2]+cost[i]);

3、初始化

保证dp表不越界就好dp[n-1]=cost[n-1],dp[n-2]=cost[n-2];

4、 填表顺序

从右往左

5、返回值

min(dp[0],dp[1]);

b、代码

这里有二种解题思路:

思路一:

class Solution {
public:
    int minCostClimbingStairs(vector<int>& cost) 
    {
        //处理边界情况
        int n = cost.size();
        if(n==0||n==1)return cost[n];
        //创建dp表
        vector<int> dp(n+1);
        //填表
        for(int i = 2;i<=n;i++)
        {
            dp[i] =min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
        }
        //返回
        return dp[n];
    }
};

 Leetcode 测试结果: 

 解法二:

class Solution {
public:
    int minCostClimbingStairs(vector<int>& cost)
    {
        int n = cost.size();
        //创建dp表
        vector<int> dp(n+1);
        //初始化
        dp[n-1]=cost[n-1],dp[n-2]=cost[n-2];
        //填表
        for(int i = n-3;i>=0;i--)
        {
            dp[i] = min(dp[i+1]+cost[i],dp[i+2]+cost[i]);
        }
        //返回
        return min(dp[0],dp[1]);
    }
};

 Leetcode 测试结果:  

  4、解码方法

一条包含字母 A-Z 的消息通过以下映射进行了 编码 :

'A' -> "1"
'B' -> "2"
...
'Z' -> "26"

要 解码 已编码的消息,所有数字必须基于上述映射的方法,反向映射回字母(可能有多种方法)。例如,"11106" 可以映射为:

  • "AAJF" ,将消息分组为 (1 1 10 6)
  • "KJF" ,将消息分组为 (11 10 6)

注意,消息不能分组为  (1 11 06) ,因为 "06" 不能映射为 "F" ,这是由于 "6" 和 "06" 在映射中并不等价。

给你一个只含数字的 非空 字符串 s ,请计算并返回 解码 方法的 总数 。

题目数据保证答案肯定是一个 32 位 的整数。

 

示例 1:

输入:s = "12"
输出:2
解释:它可以解码为 "AB"(1 2)或者 "L"(12)。

示例 2:

输入:s = "226"
输出:3
解释:它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。

示例 3:

输入:s = "06"
输出:0
解释:"06" 无法映射到 "F" ,因为存在前导零("6" 和 "06" 并不等价)。

提示:

  • 1 <= s.length <= 100
  • s 只包含数字,并且可能包含前导零。

a、解题思路 

看我们题目后,根据经验此题位动态规划解题

1、转态表示

首先我们想以i位置为结尾表示什么

dp[i]表示:以i位置结尾的时候,解码的方法有多少种

 2、状态转移方程

根据最近的一个位置划分

让s[i]单独解码的时候,假设a=s[i]

  • 成功,a!='0'(或者说是a>='1'&&a<='9'),解码的种类有dp[i-1]种
  • 失败为0

让s[i-1]和s[i]组合进行解码 假设组合为b

  • 成功b>='10'&&b<='26',解码的种类有dp[i-2]种
  • 失败为0

有同学可能会想为什么不让dp[i]和dp[i+1]进行组合,但是大家 要明白,填表到dp[i]的时候,我们是知道dp[i-1]有多少种解码,但是我们不知道dp[i+1]有多少种解码。

所以状态转移方法为

单独解码

dp[i] +=dp[i-1];

组合解码

dp[i]=dp[i-2];

3、初始化

保证dp表

dp[0] = s[0]!='0';

if(s[0]!='0'&&s[1]!='0') dp[1] +=dp[0];

//这里我们还要把组合转换为数字进行判断

int t = (s[0]-'0')*10+(s[1]-'0');

if(t>=10&&t<=26) dp[1] +=1;

4、 填表顺序

从左往右

5、返回值

dp[n-1]

b、代码

class Solution {
public:
    int numDecodings(string s)
    {
        //创建dp表
        int n = s.size();
        vector<int> dp(n);
        //初始化
        dp[0] = s[0]!='0';
        //处理边界情况
        if(n==1) return dp[0];
        //单解码
        if(s[0]!='0'&&s[1]!='0') dp[1] +=dp[0];
        //组合起来
        int t = (s[0]-'0')*10+(s[1]-'0');
        if(t>=10&&t<=26) dp[1] +=1;

        //填表
        for(int i = 2;i<n;i++)
        {
            //单解码
            if(s[i]!='0') dp[i] +=dp[i-1];
            //双解码
            int t = (s[i-1]-'0')*10+(s[i]-'0');
            if(t>=10&&t<=26) dp[i] +=dp[i-2];
        }

        //返回
        return dp[n-1];
    }
};

 Leetcode 测试结果: 

c、代码优化 

不知道大家分发现没,我们在初始化的代码和填表的代码,有着非常相似的特色,那我们能不能进行优化呢?

其实是可以的,多一个数组的空间就可以了。

简单的理解就是,把初始化的过程和填表合并了。但要注意二个问题:

那个虚拟节点dp[0]填写多少?后面大家做都了这种题,很多情况下都是填写0但,但是这里却是填写dp[0]=1; 

为什么了,因为我们这里要保证后面填写的正确

比如:在进双解码的时候dp[i]+=dp[i-2],如何i=2时候,这里我们吧dp[0]初始化为0就会漏掉这种情况。

下标映射关系如上图。

class Solution {
public:
    int numDecodings(string s)
    {
        //创建dp表
        int n = s.size();
        vector<int> dp(n+1);
        //初始化
        dp[0] = 1;//保证后面的填表的正确性
        //处理边界情况
        dp[1] = s[1-1]!='0';
        if(n==1) return dp[1];
        //填表
        for(int i = 2;i<=n;i++)
        {
            //单解码
            if(s[i-1]!='0') dp[i] +=dp[i-1];
            //双解码
            int t = (s[i-2]-'0')*10+(s[i-1]-'0');
            if(t>=10&&t<=26) dp[i] +=dp[i-2];
        }

        //返回
        return dp[n];
    }
};

 Leetcode 测试结果:  

 5、不同路径(medium)

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。

问总共有多少条不同的路径?

 

示例 1:

输入:m = 3, n = 7
输出:28

示例 2:

输入:m = 3, n = 2
输出:3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
1. 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右
3. 向下 -> 向右 -> 向下

示例 3:

输入:m = 7, n = 3
输出:28

示例 4:

输入:m = 3, n = 3
输出:6

提示:

  • 1 <= m, n <= 100
  • 题目数据保证答案小于等于 2 * 109

a、解题思路 

看我们题目后,根据经验此题位动态规划解题

1、转态表示

首先我们想以i,j位置为结尾表示什么

dp[i][j表示:以i,j位置结尾的时候,机器人到这里有多少条路径

 2、状态转移方程

根据最近的一个位置划分

我要求到[i,j] 路径,本质上就是求dp[i - 1][j] + dp[i][j - 1]的路径和

所以状态转移方法为

dp[i][j] = dp[i-1][j]+dp[i][j-1];

3、初始化

这里我们要初始化,就是在二维数组多开一行和一列,但我们要思路多开的行列填什么呢(一切都是为了填表走服务)?,很明显,在根据dp[i][j] = dp[i-1][j]+dp[i][j-1];填写表格的时候,走一步就到终点,那最外层从从到都应该填1(dp[i][j表示:以i,j位置结尾的时候,机器人到这里有多少条路径),为达到这不目的,应该把dp[0][1]=1其余为0。

4、 填表顺序

从上往下填写每一行,每一行都是从左往又开始填写 

5、返回值

dp[m][n]

b、代码

class Solution {
public:
    int uniquePaths(int m, int n)
    {
        //创建二维dp表
        vector<vector<int>> dp(m + 1, vector<int>(n + 1));
        //初始化
        dp[0][1] = 1;
        //填表
        for (int i = 1; i <= m; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
            }
        }
        return dp[m][n];
    }
};

 Leetcode 测试结果:   

 

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

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

相关文章

LeetCode-02

225. 用队列实现栈 用两个队列实现栈的功能&#xff0c;思路如下&#xff1a; 往空队列中放新元素把非空队列中的元素依次放入刚才添加了新元素的队列&#xff0c;直到非空队列变为空队列 class MyStack(object):def __init__(self):self.queue1 []self.queue2 []def push(…

thymeleaf 一个莫名其妙的错误提示 org.attoparser.ParseException

thymeleaf 一个莫名其妙的错误提示 介绍 开发过程中遇到一个莫名奇妙的错误&#xff0c;一时竟然不知道怎么解决&#xff0c;找官网也没有找到 问题 页面显示 错误日志 org.attoparser.ParseException: (Line 96, Column 5) Malformed markup: Attribute “}” appears m…

医学大数据|统计基础|医学统计学(笔记):开学说明与目录

开始学习统计基础&#xff0c;参考教材&#xff1a;医学统计学第五版 点点关注一切来学习吧 责任编辑&#xff1a;医学大数据刘刘老师&#xff1a;头部医疗大数据公司医学科学部研究员 邮箱&#xff1a;897282268qq.com 久菜盒子工作室 我们是&#xff1a;985硕博/美国全奖…

【开源】SpringBoot框架开发数据可视化的智慧河南大屏

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统展示四、核心代码4.1 数据模块 A4.2 数据模块 B4.3 数据模块 C4.4 数据模块 D4.5 数据模块 E 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的数据可视化的智慧河南大屏&#xff0c;包含了GDP、…

js面试 forEach ,map,for ,for in , for of

forEach ,map&#xff0c;for ,for in , for of 1 forEach 回调3个参数value&#xff0c;index&#xff0c;arr&#xff08;原数组&#xff09; 2 map 1&#xff1a;map() 不会改变原始数组 2&#xff1a;函数的作用是对数组中的每一个元素进行处理&#xff0c;返回新的元素…

动态规划(算法竞赛、蓝桥杯)--背包DP求具体方案

1、B站视频链接&#xff1a;E20 背包DP 求具体方案_哔哩哔哩_bilibili #include <bits/stdc.h> using namespace std; const int N1010; int v[N],w[N]; int f[N][N],p[N][N];int main(){int n,m;cin>>n>>m;for(int i1;i<n;i)cin>>v[i]>>w[i…

cmd模式下启动mysql

1.打开cmd输入services.msc&#xff0c;找到MYSQL&#xff0c;右击属性&#xff0c;找到可执行文件路径&#xff0c;加载到环境变量。 2.打开cmd&#xff0c;启动MYSQL&#xff1a;输入net start mysql; 3.登陆MYSQL&#xff0c;需要管理权限&#xff1b; 输入&#xff1a;my…

day34贪心算法 part03

1005. K 次取反后最大化的数组和 简单 给你一个整数数组 nums 和一个整数 k &#xff0c;按以下方法修改该数组&#xff1a; 选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。 重复这个过程恰好 k 次。可以多次选择同一个下标 i 。 以这种方式修改数组后&#xff0c;返回数…

达梦数据库查询语句内存溢出问题解决

背景&#xff1a;达梦数据库使用过程中&#xff0c;某天突然服务宕机&#xff0c;导致各类后端服务无法注册到nacos上&#xff0c;重启之后nacos正常启动&#xff0c;可执行一条两千多条数据量的连表查询时间很长&#xff0c;甚至会报错&#xff0c;经查看日志发现在查询过程中…

【InternLM 笔记】使用InternStudio 体验书生·浦语2-chat-1.8b随记

书生浦语2-chat-1.8b 介绍 书生浦语-1.8B (InternLM2-1.8B) 是第二代浦语模型系列的18亿参数版本。为了方便用户使用和研究&#xff0c;书生浦语-1.8B (InternLM2-1.8B) 共有三个版本的开源模型&#xff0c;他们分别是&#xff1a; InternLM2-1.8B: 具有高质量和高适应灵活性…

找不到emp.dll如何处理?emp.dll丢失的多种的解决方法分享

在计算机游戏中&#xff0c;当特定的核心文件emp.dll发生丢失时&#xff0c;可能会引发一系列影响游戏运行的问题。由于emp.dll通常是游戏运行所必需的动态链接库文件&#xff0c;它的缺失会导致游戏无法正常启动或加载&#xff0c;玩家可能面临“无法进入游戏”的尴尬境地。其…

AI技术初探:普通人ALL IN AI入门指南

自从去年ChatGPT如流星划过夜空&#xff0c;照亮了整个AI领域&#xff0c;它所带来的技术革新与热潮仿佛一场无声的暴风雨&#xff0c;席卷了全球的科技圈。身为一名低阶IT从业者&#xff0c;感觉这太高大上了&#xff0c;与我的工作有毛线关系。 但是&#xff0c;AI技术的飞速…

【海贼王的数据航海:利用数据结构成为数据海洋的霸主】链表—双向链表

目录 往期 1 -> 带头双向循环链表(双链表) 1.1 -> 接口声明 1.2 -> 接口实现 1.2.1 -> 双向链表初始化 1.2.2 -> 动态申请一个结点 1.2.3 -> 双向链表销毁 1.2.4 -> 双向链表打印 1.2.5 -> 双向链表判空 1.2.6 -> 双向链表尾插 1.2.7 -&…

枚举——完美立方算法

枚举 基于逐个尝试答案的一种问题求解策略 例如&#xff1a;求小于N的最大素数 找不到一个数学公式&#xff0c;使得根据N就可以计算出这个素数 N-1是素数吗&#xff1f;N-2是素数吗&#xff1f; …… 判断N-i是否是素数的问题 转化成求小于N的全部素数&#xff08;可以用筛法…

2024最佳steam搬砖项目,日入5000,保姆级教程,小白无脑操作

今天给带来的项目是“2024最佳steam搬砖项目&#xff0c;日入5000&#xff0c;保姆级教程&#xff0c;小白无脑操作” 二、项目准备 需要下载如下图所显示的app&#xff0c;一个是steam&#xff0c;一个是国内交易的网易buff 安装好了之后就可以开始实操了&#xff0c;国内外汇…

如何在Linux使用Docker部署Redis并结合内网穿透实现公网远程连接本地数据库

文章目录 前言1. 安装Docker步骤2. 使用docker拉取redis镜像3. 启动redis容器4. 本地连接测试4.1 安装redis图形化界面工具4.2 使用RDM连接测试 5. 公网远程访问本地redis5.1 内网穿透工具安装5.2 创建远程连接公网地址5.3 使用固定TCP地址远程访问 正文开始前给大家推荐个网站…

BUUCTF---[ACTF2020 新生赛]BackupFile1

1.题目描述 2.题目提示backup file &#xff0c;是备份文件的意思。点开链接&#xff0c;页面提示 3.查看源码没有什么有用信息&#xff0c;也没有登录界面&#xff0c;所以也不会用到蚁剑链接来找备份文件&#xff0c;所以大概率就是通过构造playload来查找备份文件。 4.备份…

Vue.js 深度解析:nextTick 原理与应用

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

【力扣hot100】刷题笔记Day21

前言 快乐周日&#xff0c;做了个美梦睡了个懒觉&#xff0c;组会前刷刷栈的题吧 20. 有效的括号 - 力扣&#xff08;LeetCode&#xff09; 辅助栈 class Solution:def isValid(self, s: str) -> bool:dic {):(,]:[,}:{}st []for c in s:if st and c in dic:if dic[c] …

JavaScript实现鼠标移动特效

关键代码&#xff1a; <script>document.onmousemove function (e) {// 加div节点var div document.createElement(div);div.style.width 5px;div.style.height 5px;// 加img节点var img document.createElement(img);// 将Img追加到div里面。div.appendChild(img);…