【刷题之路】LeetCode 746. 使用最小花费爬楼梯

news/2024/6/18 21:08:58 标签: leetcode, 算法, 动态规划, c语言

【刷题之路】LeetCode 746. 使用最小花费爬楼梯

  • 一、题目描述
  • 二、解题

一、题目描述

原题连接: 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 。

二、解题

方法——动态规划

思路分析

其实这次的动态规划思路与青蛙跳台阶的思路非常类似,
既然题目已经规定了我们每次只能选择向上爬一个或者两个台阶,
也就说明了我们登上第n级台阶一定是从第n - 1或者n - 2级台阶爬上来的,
只不过我们每次都要选择两个中费用最小的罢了。
而对于到达n - 1或n - 2级台阶的最少费用也是用同样的方法求的。
由于题目中说到可以选择下表0或下标1作为初始台阶,
因此我们可以创建一个长度为n + 1的数组dp,dp[i]表示到达下标i的最小花费,
我们将dp[0]和dp[1]都初始化为0,
当2 <= i <= n时,我们可以选择从下标为i - 1的台阶花费cost[i - 1]向上爬1个台阶到下标为i的台阶,
也可以从下标为i - 2的台阶花费cost[i - 2]向上爬2个台阶到达下标为i的台阶。
只不过我们要选择其中费用较少的。
故状态转移方程为:
dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2])
这样,当我们一直算到dp[n]时,dp[n]即为到达楼层顶部的最小花费。

代码实现

// 有了以上思路,那我们写起代码来也就水到渠成了:

int Min(int x, int y) {
	return x < y ? x : y;
}
int minCostClimbingStairs1(int* cost, int costSize) {
	assert(cost);
	// 先模拟一个一维数组
	int* dp = (int*)malloc((costSize + 1) * sizeof(int));
	if (NULL == dp) {
		perror("minCostClimbingStairs");
		return -1;
	}
	int result = 0;
	dp[0] = 0;
	dp[1] = 0;
	int i = 0;
	for (i = 2; i < costSize + 1; i++) {
		dp[i] = Min(dp[i - 2] + cost[i - 2], dp[i - 1] + cost[i - 1]);
	}
	result = dp[costSize];
	free(dp);
	dp = NULL;
	return result;
}

时间复杂度:O(n),n为cost数组的长度。
空间复杂度:O(n),n为cost数组的长度,我们需要用到n+1个额外的整型空间来存储爬到每个台阶的最少花费,股空间复杂度为O(n)。

改进

改进思路:
注意到上面的代码在当2 <= i <= n时,dp[i] 只与dp[i - 1]和dp[i - 2]有关,那我们就可以使用滚动数组的思想,只维护这三个变量,从而将空间复杂度降到O(1)。
代码实现:
有了以上改进思路,那我们再写起代码来也就水到渠成了:

int minCostClimbingStairs1(int* cost, int costSize) {
	assert(cost);
	int prev = 0;// 存储"动态的"到达第n - 2个台阶所要最少花费
	int curr = 0; // 存储"动态的"到达第n - 1个台阶所要最少花费
	int next = 0; // 存储"动态的"到达第n个台阶所要最少花费
	int i = 0;
	for (i = 2; i < costSize + 1; i++) {
		next = Min(prev + cost[i - 2], curr + cost[i - 1]);
		prev = curr;
		curr = next;
	}
	return next;
}

时间复杂度:O(n),n为cost数组的长度。
空间复杂度:O(1),我们只需要用到常数级的额外空间。


http://www.niftyadmin.cn/n/177918.html

相关文章

JAVA---数据输入与输出

1.什么是输入流与输出流 在Java中&#xff0c;把所有的输入和输出都当作流&#xff08;stream&#xff09;来处理。流是按一定顺序排列的数据集合。例如&#xff0c;从键盘或文件输入的数据&#xff0c;向显示器或文件输出的数据等都可以看作是一个个的数据流。 输入数据时&…

网络编程套接字( TCP协议通讯流程)

目录 1、绑定失败问题 2、TCP协议通讯流程 三次握手的过程 数据传输的过程 四次挥手的过程 TCP和UDP对比 1、绑定失败问题 当我们测试网络代码时&#xff0c;先将服务端绑定8080端口运行&#xff0c;然后运行客户端&#xff0c;并让客户端连接当前服务器&#xff1a; 当有客户…

摸着OpenAI过河,百度文心一言能否“重拳出击”?

“文心一言”对标ChatGPT&#xff0c;饱含争议。文心一言作为一款语言大模型&#xff0c;并提出了自己在技术对就业的影响方面的理解&#xff0c;现阶段正处于摸着OpenAI过河的时候&#xff0c;路该如何走&#xff1f; GPT-4太惊艳&#xff0c;压力给到文心一言 这段时间&…

Android生成签名证书(.keystore)

命令行方式&#xff1a; 首先安装JRE环境&#xff0c;然后使用JRE自带的keytool命令生成签名证书。 keytool -genkey -alias testalias -keyalg RSA -keysize 2048 -validity 36500 -keystore test.keystore -alias是证书别名&#xff0c;建议使用英文字母和数字 -keystore是…

Spring入门之反射机制

Spring相关概念1.1初始Spring在这一节&#xff0c;主要通过以下两个点来了解下Spring:1.1.1Spring家族官网:https://spring.io&#xff0c;从官网我们可以大概了解到&#xff1a;Spring能做什么:用以开发web、微服务以及分布式系统等光这三块就已经占了JavaEE开发的九成多。Spr…

时不我待,拥抱趋势,开源IM项目OpenIM技术简介

坚持开源 开源的理念是基于共享、合作和透明的原则&#xff0c;将软件、代码等知识资源公开并允许他人使用、修改和重新分发&#xff0c;以促进创新和发展。以下是几个开源的优点&#xff1a; 创新&#xff1a;开源可以促进创新&#xff0c;通过让其他人改进或扩展已有的代码…

【思维模型】五分钟了解<金字塔原理>,为什么学习金字塔原理?什么是金字塔原理?如何应用金字塔原理?

【思维模型】五分钟了解&#xff1c;金字塔原理&#xff1e;&#xff0c;为什么学习金字塔原理&#xff1f;什么是金字塔原理&#xff1f;如何应用金字塔原理&#xff1f;1. 为什么学习金字塔原理&#xff1f;2. 什么是金字塔原理&#xff1f;3. 如何应用金字塔原理&#xff1f…

kotlin基础知识复习

kotlin基础知识复习range 范围 从哪里 到哪里Double转Int与类型初始化尽量使用内联函数inlineList和set集合防止空指针和数据获取list去重Mapfield 关键字学习防范竞太条件构造函数运算符重载枚举泛型复习泛型约束中缀表达式重命名了解KT的变换函数KT单例类似java的双重校验效果…