力扣练习4.11

2024-04-12 11:12
文章标签 力扣 练习 4.11

本文主要是介绍力扣练习4.11,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

452. 用最少数量的箭引爆气球

不考虑y轴,可以将其转换为重叠区间的问题。将同属于一个重叠区间的小区间合并为一个区间,加上不重叠的区间,即是所求数量。
更加简化:如果是非重叠区间才加1,因为两个大的重叠区间间肯定是非重叠的。

class Solution:def findMinArrowShots(self, points: List[List[int]]) -> int:if not points:return 0# 根据右区间排序points.sort(key=lambda x: x[1])# 结果,所需数量res = 1 # 初始化为1,这样当仅有一个区间时也能正确返回# 区间末尾end = points[0][1]# 遍历剩余区间for i in range(1, len(points)):# 如果当前区间左界超过了区间末尾,说明不重叠if points[i][0] > end:res += 1 # 结果加一end = points[i][1] # 更新区间末尾return res

1710. 卡车上的最大单元数

贪婪算法,每次优先使用最能装的箱子,也要判断箱子数和该类箱子数的大小。

class Solution:def maximumUnits(self, boxTypes: List[List[int]], truckSize: int) -> int:# 结果数res = 0# 根据单元数倒排boxTypes.sort(key=lambda x: x[1], reverse=True)# 索引i = 0# 限定循环条件while truckSize > 0 and i < len(boxTypes):# 如果说箱子数比该类箱子多,就使用全部该箱子if boxTypes[i][0] <=  truckSize:res += boxTypes[i][0] * boxTypes[i][1]truckSize -= boxTypes[i][0] # 更新箱子数# 否则,只能使用全部箱子数else:res += truckSize * boxTypes[i][1]truckSize = 0 # 更新箱子数i += 1 # 查找下一类箱子return res

494. 目标和

问题转化为0-1背包问题

题目要求我们计算通过在nums数组中的每个数字前添加+-,使得它们的总和等于给定的目标值target的方法数。实际上,这个问题可以转化为一个经典的0-1背包问题。

首先,假设我们把所有选用+的数字放入一个背包A中,所有选用-的数字放入另一个背包B中。那么,背包A的总和减去背包B的总和应该等于target。同时,背包A和背包B中数字的总和加起来就是nums数组中所有数字的总和,记为sum。基于这两个条件,我们可以得到以下两个等式:

  1. sumA - sumB = target
  2. sumA + sumB = sum

通过解这两个等式,我们可以得到 sumA = (target + sum) / 2。这意味着问题转化为了寻找nums数组中有多少种组合,使得这些组合的和等于(target + sum) / 2

解决0-1背包问题

这个转化后的问题是一个标准的0-1背包问题:给定一个容量为(target + sum) / 2的背包,nums数组中的每个数字都可以选择放入或不放入背包,求有多少种方法可以恰好填满背包。

我们可以使用动态规划来解决这个问题。定义一个一维数组dp,其中dp[j]表示用nums数组中的数字填满容量为j的背包的方法数。初始化dp[0] = 1,表示容量为0的背包有一种填法(即不放入任何数字)。

然后,对于nums数组中的每个数字num,我们更新dp数组:对于每个容量j(从(target + sum) / 2num),如果j >= num,则dp[j] += dp[j - num]。这表示如果当前数字可以放入容量为j的背包中,那么填满容量为j的背包的方法数就等于之前填满容量为j的方法数(不放入当前数字)加上填满容量为j - num的方法数(放入当前数字)。

代码实现
class Solution:def findTargetSumWays(self, nums: List[int], target: int) -> int:total_sum = sum(nums)if abs(target) > total_sum or (target + total_sum) % 2 != 0:return 0package_a = (target + total_sum) // 2dp = [0] * (package_a + 1)dp[0] = 1for num in nums:for j in range(package_a, num - 1, -1):dp[j] += dp[j - num]return dp[package_a]
示例

输入: nums = [1, 1, 1, 1, 1], target = 3 输出: 5 解释: 有五种方法使得和为3:

  • +1+1+1-1-1
  • +1+1-1+1-1
  • +1-1+1+1-1
  • -1+1+1+1+1
  • +1-1-1+1+1

通过将问题转化为0-1背包问题,并应用动态规划方法,我们可以高效地求解出结果。

1137. 第 N 个泰波那契数

使用动态规划,下面是直接规划

class Solution:def tribonacci(self, n: int) -> int:# 直接在状态数组dp中初始化前三个Tribonacci数dp = [0, 1, 1] + [0] * (n - 2)# 从第4个数开始计算(索引3),因为前三个数已经初始化for i in range(3, n + 1):dp[i] = dp[i - 3] + dp[i - 2] + dp[i - 1]return dp[n]

规避了要判断n是否小于3的操作,因为直接对dp的前三个进行赋值。
dp数组的前三个值被初始化为[0, 1, 1],这对应于n = 0、n = 1和n = 2的情况。如果n小于3,dp[n]将直接返回正确的结果,无需额外的条件判断。对于n >= 3的情况,for循环将按照Tribonacci数的定义计算每个数值,并存储在dp数组中。最后,直接返回dp[n]作为结果。

记忆化搜索方法:

class Solution:def tribonacci(self, n: int) -> int:# 保存记忆memo = [0 for _ in range(n+1)]return self.do(n, memo)def do(self, n, memo):if n == 0:return 0elif n < 3:return 1# 检查是否已经计算过if memo[n] != 0:return memo[n]# 如果没有被计算过memo[n] = self.do(n-3, memo) + self.do(n-2, memo) + self.do(n-1, memo)return memo[n]

576. 出界的路径数

题目概述

题目“576.
出界的路径数”要求计算一个点从网格中的特定位置开始,最多移动N步后,有多少种路径可以使它移出网格的边界。每一步,这个点可以向上、下、左、右四个方向之一移动。

解题思路

解决这个问题的关键是理解我们如何使用动态规划(DP)来跟踪每一步移动后各个位置的路径数量,并最终计算出所有导致出界的路径。

动态规划

  1. 定义状态: 我们定义一个二维数组dp[x][y]来表示当前步骤中从起始位置到达(x, y)的路径数。
  2. 状态转移: 对于每一步,我们根据前一步的dp数组计算当前步的dp数组。如果从(x, y)出发的下一步移动会导致出界,则将这部分路径数累加到最终的计数中。
  3. 初始化: 在第0步,我们将起始位置(i, j)的路径数设为1,因为在没有移动之前,存在一条路径停留在起点。

为了避免重复计算和节省空间,我们可以使用滚动数组技巧,即只维护两个二维数组交替表示当前步和前一步的状态。

边界处理

由于每一步移动都有可能导致点移出边界,我们需要在每一步检查四个方向的移动是否会导致出界。如果是,我们就把这次移动对应的路径数加到最终的计数中。

取模操作

由于路径数可能非常大,题目要求返回结果对10^9 + 7取模的值。这意味着每次累加路径数后,我们都应该对结果进行取模,以保证结果在合法的整数范围内。

代码实现

MOD = 10**9 + 7  # 定义模数,用于取模操作,防止整数溢出class Solution:def findPaths(self, m: int, n: int, N: int, i: int, j: int) -> int:if N == 0: return 0  # 如果没有移动次数,直接返回0dp = [[0] * n for _ in range(m)]  # 初始化dp数组,存储每个位置的路径数dp[i][j] = 1  # 将起始位置的路径数设为1count = 0  # 初始化出界路径的计数器for step in range(1, N+1):  # 遍历每一步temp = [[0] * n for _ in range(m)]  # 初始化临时数组,用于计算下一步的路径数for x in range(m):  # 遍历每个位置for y in range(n):for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:  # 遍历四个方向nx, ny = x + dx, y + dy  # 计算新位置if 0 <= nx < m and 0 <= ny < n:  # 如果新位置在网格内temp[x][y] += dp[nx][ny]  # 累加路径数到临时数组else:  # 如果新位置出界count += dp[x][y]  # 累加当前位置的路径数到出界计数器temp[x][y] %= MOD  # 对每一步的结果取模,防止溢出dp = temp  # 将临时数组的结果赋值给dp,为下一步做准备return count % MOD  # 返回最终的出界路径数,并对结果取模

示例

假设m = 2, n = 2, N = 2, i = 0, j = 0,则有6种路径可以在2步内从(0, 0)移出网格边界。

通过逐步应用动态规划并在每一步累加出界的路径数,我们可以找到从给定起始位置移动N步后出界的所有路径数。这种方法通过避免重复计算并优化空间使用,有效解决了问题。

这篇关于力扣练习4.11的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/896967

相关文章

RabbitMQ练习(AMQP 0-9-1 Overview)

1、What is AMQP 0-9-1 AMQP 0-9-1(高级消息队列协议)是一种网络协议,它允许遵从该协议的客户端(Publisher或者Consumer)应用程序与遵从该协议的消息中间件代理(Broker,如RabbitMQ)进行通信。 AMQP 0-9-1模型的核心概念包括消息发布者(producers/publisher)、消息(messages)、交换机(exchanges)、

【Rust练习】12.枚举

练习题来自:https://practice-zh.course.rs/compound-types/enum.html 1 // 修复错误enum Number {Zero,One,Two,}enum Number1 {Zero = 0,One,Two,}// C语言风格的枚举定义enum Number2 {Zero = 0.0,One = 1.0,Two = 2.0,}fn m

MySql 事务练习

事务(transaction) -- 事务 transaction-- 事务是一组操作的集合,是一个不可分割的工作单位,事务会将所有的操作作为一个整体一起向系统提交或撤销请求-- 事务的操作要么同时成功,要么同时失败-- MySql的事务默认是自动提交的,当执行一个DML语句,MySql会立即自动隐式提交事务-- 常见案例:银行转账-- 逻辑:A给B转账1000:1.查询

html css jquery选项卡 代码练习小项目

在学习 html 和 css jquery 结合使用的时候 做好是能尝试做一些简单的小功能,来提高自己的 逻辑能力,熟悉代码的编写语法 下面分享一段代码 使用html css jquery选项卡 代码练习 <div class="box"><dl class="tab"><dd class="active">手机</dd><dd>家电</dd><dd>服装</dd><dd>数码</dd><dd

两数之和--力扣1

两数之和 题目思路C++代码 题目 思路 根据题目要求,元素不能重复且不需要排序,我们这里使用哈希表unordered_map。注意题目说了只对应一种答案。 所以我们在循环中,使用目标值减去当前循环的nums[i],得到差值,如果我们在map中能够找到这个差值,就说明存在两个整数的和为目标值。 如果没有找到,就将当前循环的nums[i]以及下标i放入map中,以便后续查

力扣第347题 前K个高频元素

前言 记录一下刷题历程 力扣第347题 前K个高频元素 前K个高频元素 原题目: 分析 我们首先使用哈希表来统计数字出现的频率,然后我们使用一个桶排序。我们首先定义一个长度为n+1的数组,对于下图这个示例就是长度为7的数组。为什么需要一个长度为n+1的数组呢?假如说总共有三个数字都为1,那么我们需要把这个1放在数组下标为3的位置,假如说数组长度为n,对于这个例子就是长度为3,那么它的

014.Python爬虫系列_解析练习

我 的 个 人 主 页:👉👉 失心疯的个人主页 👈👈 入 门 教 程 推 荐 :👉👉 Python零基础入门教程合集 👈👈 虚 拟 环 境 搭 建 :👉👉 Python项目虚拟环境(超详细讲解) 👈👈 PyQt5 系 列 教 程:👉👉 Python GUI(PyQt5)文章合集 👈👈 Oracle数据库教程:👉👉 Oracle数据库文章合集 👈👈 优

如何快速练习键盘盲打

盲打是指在不看键盘的情况下进行打字,这样可以显著提高打字速度和效率。以下是一些练习盲打的方法: 熟悉键盘布局:首先,你需要熟悉键盘上的字母和符号的位置。可以通过键盘图或者键盘贴纸来帮助记忆。 使用在线打字练习工具:有许多在线的打字练习网站,如Typing.com、10FastFingers等,它们提供了不同难度的练习和测试。 练习基本键位:先从学习手指放在键盘上的“家位”开始,通常是左手的

anaconda3下的python编程练习-csv翻译器

相关理解和命令 一、环境配置1、conda命令2、pip命令3、python命令 二、开发思路三、开发步骤 一、环境配置 1、conda命令 镜像源配置 conda config --show channels //查看镜像源conda config --remove-key channels //删除添加源,恢复默认源#添加镜像源conda config --ad

推荐练习键盘盲打的网站

对于初学者来说,以下是一些推荐的在线打字练习网站: 打字侠:这是一个专业的在线打字练习平台,提供科学合理的课程设置和个性化学习计划,适合各个水平的用户。它还提供实时反馈和数据分析,帮助你提升打字速度和准确度。 dazidazi.com:这个网站提供了基础的打字练习,适合初学者从零开始学习打字。 Type.fun打字星球:提供了丰富的盲打课程和科学的打字课程设计,还有诗词歌赋、经典名著等多样