千锤百炼之每日算法(一)

news2024/11/30 10:43:38

 

目录

题外话

正题

第一题

第一题思路

第一题代码详解

第二题

第二题思路

动态规划

解法一

解法一代码详解

解法二

第三题

第三题思路

第三题代码详解

小结


题外话

从今天开始,每天都会更新算法题,一天就三道题

大家最好采用码形结合的方式,也就是代码和图形结合,这样理解真的很快

而且这里是写文章,不是视频,大家理解起来肯定会吃力一点

需要画图的题,我一定会给大家尽量画清楚,帮助大家理解

想学习的人,那怕全是文字,也会一点一点去琢磨

不想学习的人,哪怕是视频喂到他嘴里,他都不想去动脑思考一下

喜欢的美女帅哥们,给个三连好嘛!!!(点赞关注收藏!!!) 

正题

第一题

帮助牛牛寄快递

牛牛正在寄快递,他了解到快递在 1kg 以内的按起步价 20 元计算

超出部分按每 kg 1元计算不足 1kg 部分按 1kg计算

如果加急的话要额外付五元,请问牛牛总共要支付多少快递费

第一行输入一个单精度浮点数 a 和一个字符 b
a 表示牛牛要寄的快递的重量,b表示牛牛是否选择加急,'y' 表示加急 ,'n' 表示不加急。

第一题思路

邮费共有四种情况
1.1kg以内是否加急,总费用等于是否加急费用加上起步价
2.1kg以外是否加急,总费用等于是否加急费用加上起步价加上从超出1kg以外费用

这道题有一个方法非常关键,掌握了这个方法这道题没啥难度

Math.ceil(double d)

简单说一下,传入一个双精度浮点型,会自动向上取整,返回值是double类型

例如

double  d=15.38;

System.out.println(Math.ceil(d));

输出结果就是16.0

放到这道题当中,我们可以知道,当牛牛的邮寄重量超过1kg,而且不足1kg,就会按照1kg收费

我们都知道,要解决关键问题,一定要找到问题的关键!!

所以向上取整Math.ceil(double d)就正好解决了了这个关键问题 

第一题代码详解

public int test1()
{
    Scanner s=new Scanner(System.in);
    //输入快递重量
    float weight=s.nextFloat();
    //输入'y'和'n'表示是否加急,转换成字符串形式
    char ch=s.next().charAt(0);
    //只要邮寄就至少需要20邮费
    int money=20;
    //当重量小于等于1的时候
    if(weight<=1)
    {
        //加急就加5,不加急就加0
       money+=ch=='y'?5:0;
    }
    else {
    //当重量大于1的时候,判断是否加急,加急的话就用Math.ceil方法取最大整数,减去1kg以内,加上5,不加急就加0
       money+=ch=='y'?5+Math.ceil(weight-1):Math.ceil(weight-1);
    }

//最后返回邮寄需要支付的费用
    return money;
}

第二题

最小支付爬楼梯问题

给定一个整数数组cost,其中cost[i]是从楼梯第i 台阶向上爬需要支付的费用
 下标从0开始。一旦你支付此费用,即可选择向上爬一个或者两个台阶。
你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。
请你计算并返回达到楼梯顶部的最低花费。

输入描述:
第一行输入一个正整数 n ,表示数组 cost 的长度。
第二行输入 n 个正整数,表示数组 cost 的值。

输出描述:
输出最低花费

示例1.

示例2.

 

第二题思路

 第二题需要一个算法思想,就像大家在解答鸡兔同笼问题,是不是需要一元二次方程?

但是这个算法思想比一元二次方程灵活许多

动态规划

动态规划一共分为五个步骤

1.状态表示

2.状态转移方程

3.初始化 

4.填表顺序

5.返回值

状态表示就是思路,找到题目给你的信息

比如鸡兔同笼,你需要知道一共笼子里几条腿?你还需要知到鸡是两条腿,兔子是四条腿没错吧?!

你找到的状态表示不一样,下面步骤也会不一样

大家可以把这道题和数学应用题联系起来

比如鸡兔同笼问题,你设x为鸡数量,y为兔数量,是一种解题方法,你设x为兔,y为鸡也是一种解题方法,

设置的未知数不一样,解题的时候写的公式也是不一样的

我们可以简单的理解状态转移方程就是鸡兔同笼问题的二元一次方程公式

你把这个公式写明白了,然后再去计算再去写答鸡有多少只,兔子有多少只

我希望大家把这道题的题目理解清楚再看题解

接下来就是这道题运用动态规划的详解

解法一

2.状态表示

以i位置为结尾,然后通过题目信息建立状态表示

dp[i]:到达i位置的最小花费

2.状态转移方程

用之前或者之后的状态,推导出dp[i]的值

由题可知我们要想到达dp[i],分两种情况

第一种:先到达i-1位置,走一步到达i位置,也就是到达i-1位置的最小花费加上cost[i-1]花费,这就是到达dp[i]花费的钱 dp[i-1]+cost[i-1]

第二种:先到达i-2位置,走两步达到i位置, 也就是到达i-2位置的最小花费加上cost[i-2]花费,这就是到达dp[i]花费的钱 dp[i-2]+cost[i-2]

我们只需要找到i-1位置到达i和i-2位置到达i位置的最小值

dp[i]=min[dp[i-1]+cost[i-1], dp[i-2]+cost[i-2]]

3.初始化

根据动态转移方程然后去初始化,先思考我们要从数组的那个下标开始走?

如果从i=0开始走,是不是会越界?从i=1开始走也会越界

所以我们要从i=2开始走

没问题吧?!

从i=2开始走的时候我们就结合动态转移公式,可以算出dp[0]和dp[1]的最小花费,也就是cost[i-1]和cost[i-2]最小值

然后继续往后走,因为前面已经算出最小值了,再往后走i=3的时候,算出的也一定是最小值

以此类推,当i走到楼顶的时候,算出来的也一定是最小值

4.填表顺序

我们需要知道从数组左边花费,然后才能知道到达数组右边的最小花费

所以是从左往右走

5.返回值

那么dp[n]就是我们到达楼梯顶部的最小花费

解法一代码详解

public int test2(int[] cost)
    {
        //保存cost元素数量,下标最大值为n-1
        int n=cost.length;


        //因为楼顶会超出cost元素数量一个,所以dp[]的元素数量为n+1,下标最大值为n,到达n说明到楼顶了
        int[] dp=new int[n+1];
        //从i=2开始,以免数组越界
        for (int i=2;i<=n;i++)
        {
            //dp[i]是到达i位置最小花费,
            // 一共有两种情况
            // 一种是到达i-1位置加上i-1位置花费
            // 一种是到达i-2位置加上i-2位置花费
            //获取上面这两种情况最小值,就是dp[i]的最小值
            dp[i]=Math.min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
        }
        return dp[n];
    }

解法二

我们解法一是通过从前往后的顺序去推导出最小花费

解法二我们就从后往前推导出最小花费

和解法一略有不同

1.状态表示

以i位置为起点,通过题目信息建立状态表示

设dp[i]从i出发到达楼顶最小花费

2.状态转移方程

想知道i位置出发到达楼顶的最小花费

我们需要知道从i+1位置出发和i+2位置出发到达楼顶的最小花费

也就是dp[i]=Math.Min(dp[i+1]+cost[i],dp[i+2]+cost[i])

我们可以先让dp[i+1]和dp[i+2]比较,然后再加上cost[i]

3.初始化

我们应该从n-1位置和n-2位置往回推

根据动态转移公式考虑越界的情况,i初始值应该等于n-3

算出n-1位置出发和n-2位置出发到达楼顶的最小值

这里我们需要初始化n-1位置出发到达楼顶的最小值,也就是cost[n-1]的花费,因为n-1直接能到楼顶,所以n-1位置出发到达楼顶最小花费就是cost[n-1]

和初始化n-2位置出发到达楼顶的最小值,也就是cost[n-2],因为n-2直接能到楼顶,没必要再上一个台阶到达n-1支付再去楼顶

为什么解法一不需要初始化??因为解法一第0个台阶和第1个台阶,就是动态转移方程的cost[i-1]和cost[i-2],可以去对比一下

而解法二这里的n-1和n-2位置出发到达楼顶的最小值咱们没有赋值

然后算出n-2位置和n-3位置出发到达楼顶的最小值

以此类推,我们从后往前算出的都是最小值

那么从0和1出发到达楼顶也一定是最小值

最后只需要算出从0和1出发到达楼顶哪个是最小值即可

4.填表顺序

我们从n-1和n-2的位置往回退,所以是从右往左的顺序

5.返回值

我们最后会得到,dp[0]和dp[1],也就是从0位置出发的最小花费和从1位置出发的最小花费

最后返回它们的最小值即可

解法二代码详解

public int test3(int[] cost)
{
    //保存cost元素数量
    int n=cost.length;


    //因为我们是从n-1,n-2位置出发到达楼顶,只需要知道n-1位置花费和n-2位置花费即可
    int[] dp=new int[n];


    //初始化n-1位置出发最小花费和n-2出发的最小花费
    dp[n-1]=cost[n-1];
    dp[n-2]=cost[n-2];


    //从i=2开始,以免数组越界
    for (int i=n-3;i>=0;i--)
    {
        //dp[i]是从i位置出发到达楼顶的最小花费,
        // 一共有两种情况,一种是到达i+1位置加上i位置花费,一种是到达i+2位置加上i位置花费
        //获取上面这两种情况最小值,就是dp[i]的最小值
        dp[i]=Math.min(dp[i+1]+cost[i],dp[i+2]+cost[i]);
    }
    return Math.min(dp[0],dp[1]);

}

第三题

两个字符串在字符串数组中最短距离问题

给定一个字符串数组strs再给定两个字符串str1和str2

返回在strs中str1与str2的最小距离
如果str1或str2为null,或不在strs中,返回-1。

示例

第三题思路

1.判断str1和str2是否为空,有一个为空直接返回-1

2.遍历str

3.我们需要创建两个变量记录分别记录str1和str2最近一次出现的位置

4.还需要创建一个最小距离变量,当str1出现之后,立刻和str2进行距离比较

5.如果遍历str结束最小距离值仍然没有改变,那就说明str中不包含str1或者str2返回-1

第三题代码详解

public int test4(String[] str,String str1,String str2)
{
    //创建min为最小距离值,str1和str2距离值最大也不会等于str数组长度
    int min=str.length;
    //s1记录str1最近出现在str数组中的下标,s2记录str1最近出现在str数组中的下标
    int s1=-1;
    int s2=-1;
    //如果str1或者str2为空直接返回-1
    if (str1==null||str2==null)
    {
        return -1;
    }
    //当他们都不为空
    else {
        //遍历str数组
        for (int i=0;i<str.length;i++)
        {
            //如果找到str1
            if (str[i].equals(str1))
            {
                //需要判断s2是否等于-1,等于-1说明str2还没有找到,min仍然为str.length
                //找到了则进行比较,此时i绝对大于s2,i-s2就是他们的距离
                //判断距离最小值
                min=Math.min(min,s2==-1?min:i-s2);
                //记录str1在str中的位置
                s1=i;
            }
            //如果找到str2
            if (str[i].equals(str2))
            {
                //需要判断s1是否等于-1,等于-1说明str1还没有找到,min仍然为str.length
                //找到了则进行比较,此时i绝对大于s1,i-s1就是他们的距离
                //判断距离最小值
                min=Math.min(min,s1==-1?min:i-s1);
                //记录str2在str中的位置
                s2=i;
            }
        }
        //最后返回min判断min是否等于数组长度,等于就说明没有找到返回-1,不等于则找到了返回min
        return min==str.length?-1:min;
    }

}

小结

到现在我还没有吃饭,饿了饿了,先去吃饭了

大家有问题再评论区留言

麻烦大家三连一下!!!(点赞关注收藏!!!)

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

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

相关文章

最新最全的Jmeter接口测试必会技能:jmeter对图片验证码的处理

jmeter对图片验证码的处理 在web端的登录接口经常会有图片验证码的输入&#xff0c;而且每次登录时图片验证码都是随机的&#xff1b;当通过jmeter做接口登录的时候要对图片验证码进行识别出图片中的字段&#xff0c;然后再登录接口中使用&#xff1b; 通过jmeter对图片验证码…

git出现错误 fail to push some refs to “xxx“

问题产生原因&#xff1a;根据测试猜测造成这一错误的原因是在码云的远程仓库上删除了一个文件,本地没有pull下来,直接进行了commit,commit到本地仓库后,如果在pull下来,也是无法提交的 问题解决办法: 使用 git pull --rebase,拉取远程仓库,并将本地仓库新的提交作为最顶层的提…

C++ 并发编程指南(11)原子操作 | 11.5、内存模型

文章目录 一、C 内存模型1、为什么需要内存模型&#xff1f; 前言 C 11标准中最重要的特性之一&#xff0c;是大多数程序员都不会关注的东西。它并不是新的语法特性&#xff0c;也不是新的类库功能&#xff0c;而是新的多线程感知内存模型。本文介绍的内存模型是指多线程编程方…

(算法版)基于二值图像数字矩阵的距离变换算法

Hi&#xff0c;大家好&#xff0c;我是半亩花海。本项目展示了欧氏距离、城市街区距离和棋盘距离变换的实现方法。通过定义一个距离变换类&#xff0c;对输入图像进行距离变换操作&#xff0c;并生成对应的距离矩阵。在示例中&#xff0c;展示了在一个480x480的全黑背景图像上设…

GPT国内怎么用?4月最新版本来了

ChatGPT镜像 今天在知乎看到一个问题&#xff1a;“平民不参与内测的话没有账号还有机会使用ChatGPT吗&#xff1f;” 从去年GPT大火到现在&#xff0c;关于GPT的消息铺天盖地&#xff0c;真要有心想要去用&#xff0c;途径很多&#xff0c;别的不说&#xff0c;国内GPT的镜像…

基于SpringBoot+Vue的疾病防控系统设计与实现(源码+文档+包运行)

一.系统概述 在如今社会上&#xff0c;关于信息上面的处理&#xff0c;没有任何一个企业或者个人会忽视&#xff0c;如何让信息急速传递&#xff0c;并且归档储存查询&#xff0c;采用之前的纸张记录模式已经不符合当前使用要求了。所以&#xff0c;对疾病防控信息管理的提升&a…

20240329-2-树模型集成学习TreeEmbedding

树模型集成学习 集成学习主要有两个思想&#xff0c;分别是bagging和boosting。树模型的集成模型都是使用树作为基模型&#xff0c;最常用的cart树&#xff0c;常见的集成模型有RandomForest、GBDT、Xgboost、Lightgbm、Catboost。 概要介绍 RandomForest 随机森林(Random …

spring的redis注解@Cacheable @Cacheput @CacheEvict的condition、unless

概述 redis的注解使用的过程中总会遇到condition和unless这两个属性&#xff0c;而且不同的注解使用注意事项不一样。本人也是错误使用之后详细查询了一下&#xff0c;作了如下的总结。 Cacheale 这个注解的使用和意义这里不多说&#xff0c;可以查看我的其他文档。这里主要说…

nginx安装在linux上

nginx主要用于反向代理和负载均衡&#xff0c;现在简单的说说如何在linux操作系统上安装nginx 第一步&#xff1a;安装依赖 yum install -y gcc-c pcre pcre-devel zlib zlib-devel openssl openssl-devel 第二步&#xff1a; 下载nginx&#xff0c;访问官网&#xff0c;ngin…

在操作系统里面打开了Ubuntu 然后vi编辑器编辑内容后没有效果了

我在vi创建项目后编写 然后一直卡着动不了 如下&#xff08;界面没有卡住 可以其他操作&#xff09; 唉&#xff1a;这是一个初学者到悲哀&#xff1a; 原因&#xff1a;是Windows编写习惯 按了Ctrl s在该系统里面就是停止输入&#xff0c;需要按ctrl q恢复输入

Workerman开启ssl方法如下

参考地址 Workerman开启ssl方法如下-遇见你与你分享 准备工作&#xff1a; 1、Workerman版本不小于3.3.7 2、PHP安装了openssl扩展 3、已经申请了证书&#xff08;pem/crt文件及key文件&#xff09;放在了/etc/nginx/conf.d/ssl下 4、配置文件 location /wss { proxy_set…

使用Java调用音乐开放API,并进行播放

使用Java调用音乐开放API&#xff0c;并进行播放 背景描述 电脑没有下载音乐软件&#xff0c;使用网页播放又不太方便&#xff0c;所有就想着使用Java语言直接调用音乐开放API&#xff0c;然后进行播放音乐。 具体代码如下&#xff0c;包含了注释 package com.lowkey.comple…

基于改进遗传算法的配电网故障定位(matlab代码)

1 主要内容 该程序复现文章《基于改进遗传算法的配电网故障定位》&#xff0c;将改进的遗传算法应用于配电网故障定位中, 并引入分级处理思想, 利用配电网呈辐射状的特点, 首先把整个配电网划分为主干支路和若干独立区域, 再利用该算法分别对各独立区域进行故障定位, 然后进行…

node.js服务器动态资源处理

一、node.js服务器动态资源处理与静态资源处理的区别&#xff1f; 静态与动态服务器主要区别于是否读取数据库&#xff0c;若然在数据库中的资料处理中将数据转换成可取用格式的结构&#xff0c;也就是说把对象转化为可传输的字节序列过程称为序列化&#xff0c;反之则为反序列…

她在《繁花》大放异彩,“浪姐”暴瘦15斤,打脸了不看好她的观众

不知不觉&#xff0c;《浪姐》已经迎来第5季了。播到第4季的时候&#xff0c;改名成《乘风破浪2023》&#xff0c;这一季叫《乘风2024》&#xff0c;和前几季相比&#xff0c;热度依然不减。 都说3个女人一台戏&#xff0c;更何况这个节目&#xff0c;每次能请到30位姐姐&…

再生龙(Clonezilla)网络克隆linux系统实现迁移——筑梦之路

官方网站&#xff1a;Clonezilla - 簡介 环境说明 源端&#xff1a;CentOS 7 操作系统的虚拟机&#xff0c;硬盘大小为 40GiB&#xff0c;分为 1GiB 的 /boot&#xff08;启动&#xff09;分区、4GiB 的 swap&#xff08;交换&#xff09;分区和 35GiB 的 /&#xff08;根&…

LeetCode236:二叉树的最近公共祖先

题目描述 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff08;一个节点也可以是…

二分查找的时间复杂度的讲解

二分查找的代码&#xff1a; 二分查找的时间复杂度&#xff1a; 最坏的情况&#xff1a; 就是找不到和查找区间只剩一个值的时候&#xff0c;这两种都是最坏的结果&#xff0c;假设查找了x次&#xff0c;达到了最坏的结果&#xff1a; N代表每一次折半区间数据的个数&#xf…

【C语言】——字符串函数的使用与模拟实现(下)

【C语言】——字符串函数的使用与模拟实现&#xff08;下&#xff09; 前言五、长度受限类字符串函数5.1、 s t r n c p y strncpy strncpy 函数5.2、 s t r n c a t strncat strncat 函数5.3、 s t r n c m p strncmp strncmp 函数 六、 s t r s t r strstr strstr 函数6.1、函…