力扣每日练习(3.20)补

2024-03-22 18:28
文章标签 力扣 每日 练习 3.20

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

322. 零钱兑换

想象你有一堆不同面值的硬币,现在的任务是用这些硬币凑出一个指定的金额,比如说11元,而且要求用的硬币数量尽可能少。

  1. 准备工作:首先,我们做了一张表(叫dp),这张表记录了从0元到目标金额(比如11元)每一个金额所需要的最少硬币数量。刚开始,我们假设每个金额所需的硬币数量都是最多的,这就像是一个最坏的情况。

  2. 开始计算:然后,我们开始尝试用手头上的每一种硬币去更新这张表。对于每一种硬币,我们看它能帮助减少哪些金额所需的硬币数量。

    • 比如,如果我们有1元和2元的硬币,我们就从1元和2元开始,一直尝试到11元,看看加入这种硬币后能不能让所需硬币数量更少。
    • 每次当我们考虑加入一个新的硬币时,我们会查看:如果我现在用这个硬币,再加上剩下的金额所需要的最少硬币数(这个信息已经在表里了),是不是比目前记录的要少。如果是,就更新这个金额所需的最少硬币数。
  3. 结果判断:最后,我们看看表中记录的目标金额所需的硬币数量是否被更新过(如果没有被更新过,说明用这些硬币凑不出这个金额),如果能凑出来,就告诉你需要的最少硬币数是多少。

class Solution:def coinChange(self, coins: List[int], amount: int) -> int:# 初始化从0到目标金额的逐个列表dp = [amount+1 for _ in range(amount+1)]dp[0] = 0 # 金额0不要任何硬币# 遍历每个硬币for c in coins:# 遍历大于等于硬币面额的金额for i in range(c, amount+1):# 核心:更新当前金额的最少所需硬币数,求 只使用当前硬币的数量 和 使用一个当前硬币+差额所需的最小硬币数 的最小值dp[i] = min(dp[i], dp[i-c]+1)# 如果指定金额的硬币数没有被更新,说明没有组合能够满足return dp[-1] if dp[-1] != amount+1 else -1

dp[i] = min(dp[i], dp[i-c]+1) 这行代码是动态规划的核心。dp[i-c]+1表示如果你选择了面额为c的硬币,那么对于剩余的金额i-c,所需的最小硬币数就是dp[i-c],再加上你这次选择的这一枚硬币(也就是+1)。min(dp[i], dp[i-c]+1)的意思是,比较当前金额i所需最小硬币数的现有值(dp[i])和使用当前面额硬币新计算得到的值(dp[i-c]+1),取二者中的较小值作为新的最小硬币数。

78. 子集

以nums = [1, 2, 3]为例。想象一下,我们有一个空盒子(temp),我们可以决定是否要把一些数字放进去。我们的目标是找出所有可能的方式来填充这个盒子,也就是所有的子集。

开始时,我们的盒子是空的。这也是一个子集,所以我们先把它加到结果列表res中。现在,res = [[]]。
递归的魔法:我们用一个函数dfs来帮助我们决定每个数字是否放入盒子。
我们从第一个数字开始,看看我们可以把它放入盒子(即列表temp),然后我们继续看下一个数字。
每当我们考虑一个数字(比如1),我们会做两件事:一次尝试把它加入盒子,另一次则不加。对于每种情况,我们都会继续向下看下一个数字,直到没有更多数字为止。
添加子集:每次我们到达数字列表的末尾时,我们的盒子里装的就是一个完整的子集。我们把这个子集的一个复制(使用list(temp)来确保我们复制的是内容,而不是引用)加到结果res中。
回溯:这个词听起来有点复杂,但实际上很简单。就是当我们考虑完一个数字(比如1)放入盒子后,我们会把它拿出来(temp.pop()),就好像我们从未做过这个决定一样。这样我们就可以回到之前的状态,然后考虑不放入1的情况。这个过程让我们能够探索所有可能的组合。
结束:当我们考虑完所有的数字后,res就包含了所有可能的子集。

class Solution:def subsets(self, nums: List[int]) -> List[List[int]]:res = []def dfs(temp, index, nums):# 直接添加当前子集到结果列表中,无需等到最后res.append(list(temp))  # 使用list(temp)来复制当前子集# 遍历从当前索引到末尾的所有元素for i in range(index, len(nums)):# 包含当前元素temp.append(nums[i])# 递归调用处理下一个元素dfs(temp, i + 1, nums)# 回溯:移除当前元素,尝试下一个选择temp.pop()# 开始递归dfs([], 0, nums)return(res)

221. 最大正方形

定义状态:我们可以定义一个二维的DP数组dp,其中dp[i][j]代表以(i, j)为右下角的最大正方形的边长。注意,这个定义是关键的,因为它让我们能够通过左边、上边和左上角的状态来决定当前位置的状态。
找到状态转移方程:对于每个位置(i, j),如果该位置的值是’1’,那么dp[i][j]应该是其左边、上边和左上角的dp值中的最小值加1。这是因为,一个位置如果要构成一个更大的正方形,它的左边、上边和左上角也必须能构成正方形。数学表达式为:dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1。
初始化:对于矩阵的第一行和第一列,dp[i][j]就直接是矩阵中的值(因为它们只能形成最大边长为1的正方形)。
遍历矩阵填充DP数组:从(1, 1)开始遍历整个矩阵,并根据状态转移方程更新DP数组。
找到最大的dp[i][j]:遍历DP数组,找到最大的值,这个值的平方即为最大正方形的面积。

创建了一个辅助矩阵,元素是int,这样就解决了对原始矩阵元素转换类型的问题,同时还有在原始矩阵里修改元素影响实际计算的问题。然后针对元素为’1’时才开始计算,同时考虑边界情况。状态转移方程是根据每一步前面的上、左、左上角的累计最小值+1决定当前1的边长,这样在本身自己是一个单位的基础上和上面的合起来就是2,依次累加

class Solution:def maximalSquare(self, matrix: List[List[str]]) -> int:# 长宽,初始化最大边长rows,cols = len(matrix), len(matrix[0])max_side = 0# 辅助矩阵,全0初始化dp = [[0]*cols for _ in range(rows)] # 遍历每个元素for r in range(rows):for c in range(cols):if matrix[r][c] != '0': # 为1才进行计算if r == 0 or c == 0: # 对于边界情况进行处理dp[r][c] = 1else: # 状态转移方程,假设当前是正方形的右下角,其值由左、上、左上的最小值决定dp[r][c] = min(dp[r][c-1], dp[r-1][c], dp[r-1][c-1]) + 1# 更新最大边长max_side = max(max_side, dp[r][c])# 边长2次方return max_side ** 2

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



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

相关文章

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)、

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点

【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.查询

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

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

每日一练7:简写单词(含链接)

1.链接 简写单词_牛客题霸_牛客网 2.题目 3.代码1(错误经验) #include <iostream>#include <string>using namespace std;int main() {string s;string ret;int count = 0;while(cin >> s)for(auto a : s){if(count == 0){if( a <=

两数之和--力扣1

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

【每日刷题】Day113

【每日刷题】Day113 🥕个人主页:开敲🍉 🔥所属专栏:每日刷题🍍 🌼文章目录🌼 1. 91. 解码方法 - 力扣(LeetCode) 2. LCR 098. 不同路径 - 力扣(LeetCode) 3. 63. 不同路径 II - 力扣(LeetCode) 1. 91. 解码方法 - 力扣(LeetCode) //思路:动态规划。 cl

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

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