leedcode 算法刷题第三十一天

1049. 最后一块石头的重量 II

有一堆石头,用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。

每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:

  • 如果 x == y,那么两块石头都会被完全粉碎;
  • 如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x

最后,最多只会剩下一块 石头。返回此石头 最小的可能重量 。如果没有石头剩下,就返回 0

示例 1:

输入:stones = [2,7,4,1,8,1]
输出:1
解释:
组合 2 和 4,得到 2,所以数组转化为 [2,7,1,8,1],
组合 7 和 8,得到 1,所以数组转化为 [2,1,1,1],
组合 2 和 1,得到 1,所以数组转化为 [1,1,1],
组合 1 和 1,得到 0,所以数组转化为 [1],这就是最优值。

示例 2:

输入:stones = [31,26,33,21,40]
输出:5

提示:

  • 1 <= stones.length <= 30
  • 1 <= stones[i] <= 100
class Solution {
public:int lastStoneWeightII(vector<int>& stones) {vector<int> dp(150001,0);int sum = 0;for(int i=0;i<stones.size();i++){sum+=stones[i];}int target = sum/2;for(int i = 0;i<stones.size();i++){for(int j = target;j>=stones[i];j--){dp[j] = max(dp[j],dp[j-stones[i]]+stones[i]);}}return sum-dp[target]-dp[target];}
};

解题思路:

问题背景

问题描述:有一堆石头,每次从中挑选两块石头碰撞,碰撞后会得到一块新石头(重量为两块石头的差值),直到只剩下一块石头或没有石头。求最后可能剩下的最小石头重量。

核心思路转化

这个问题可以转化为:

  • 将石头分成两堆,使两堆的重量尽可能接近
  • 两堆重量的差值就是最后可能剩下的最小重量

这是因为每次碰撞相当于从总重量中减去 twice of 较小的那块石头的重量,最优策略是让两堆石头重量尽可能接近。

代码原理详解

  1. 动态规划数组定义
    dp[j]表示能从石头中选出若干块,使得它们的总重量最大为j

  2. 计算目标值
    sum是所有石头的总重量
    targetsum/2,我们尝试找到不超过这个值的最大子集和

  3. 0-1 背包问题求解

    • 外层循环遍历每块石头(物品)
    • 内层循环从target往当前石头重量遍历(0-1 背包的典型做法,避免重复使用同一物品)
    • dp[j] = max(dp[j], dp[j - stones[i]] + stones[i])表示对于重量j,要么不选当前石头保持dp[j],要么选当前石头得到dp[j - stones[i]] + stones[i]
  4. 计算结果
    sum - dp[target] - dp[target]表示总重量减去两倍的最大子集和(即两堆石头的重量差)

这个解法的时间复杂度是 O (n×target),空间复杂度是 O (target),其中 n 是石头数量,target 是总重量的一半。

494. 目标和

class Solution {
public:int findTargetSumWays(vector<int>& nums, int target) {int sum = 0;for (int i = 0; i < nums.size(); i++) sum += nums[i];if (abs(target) > sum) return 0; // 此时没有方案if ((target + sum) % 2 == 1) return 0; // 此时没有方案int bagSize = (target + sum) / 2;vector<int> dp(bagSize + 1, 0);dp[0] = 1;for(int i=0;i<nums.size();i++){for(int j = bagSize;j>=nums[i];j--){dp[j] += dp[j-nums[i]];}}return dp[bagSize];}
};

给每个数字添加+-,本质上是将数组分成两组:

  • 一组数字前面加+(和为left
  • 另一组数字前面加-(和为right

根据题意,我们有:

plaintext

left - right = target  // 表达式结果等于target
left + right = sum     // 所有数字的总和

将两式相加可得:2*left = target + sum,即 left = (target + sum) / 2

因此问题转化为:找到有多少种方法可以从数组中选出一些数字,使它们的和等于 left

代码解析

  1. 边界条件判断

    if (abs(target) > sum) return 0; // 目标值的绝对值大于总和,不可能实现
    if ((target + sum) % 2 == 1) return 0; // 和为奇数,无法被2整除,没有方案
    
  2. 计算背包大小

    int bagSize = (target + sum) / 2;
    
     

    这里的bagSize就是我们要找的left值,即需要选出和为bagSize的数字组合

  3. 动态规划初始化

     
    vector<int> dp(bagSize + 1, 0);
    dp[0] = 1; // 表示凑出和为0的方法有1种(什么都不选)
    
     

    dp[j]的含义是:有多少种方法可以选出和为 j 的数字组合

  4. 填充 DP 数组

     
    for (int i = 0; i < nums.size(); i++) { // 遍历每个数字for (int j = bagSize; j >= nums[i]; j--) { // 倒序遍历背包dp[j] += dp[j - nums[i]];}
    }
    
     
    • 对于每个数字,我们可以选择 "放入背包"(即该数字前面加+)或 "不放入背包"(即该数字前面加-
    • 状态转移方程dp[j] += dp[j - nums[i]]表示:凑出和为 j 的方法数 = 不选当前数字的方法数 + 选当前数字的方法数(此时需要加上凑出 j-nums [i] 的方法数)
    • 倒序遍历是为了保证每个数字只被使用一次(0-1 背包特性)
  5. 返回结果

    return dp[bagSize];
    
     

    dp[bagSize]就是能凑出和为bagSize的方法总数,也就是我们要求的答案

示例说明

nums = [1,1,1,1,1]target = 3为例:

  • 总和sum = 5
  • bagSize = (3 + 5) / 2 = 4
  • 问题转化为:有多少种方法从数组中选出和为 4 的数字
  • 答案是 5 种,对应 5 种不同的表达式

474. 一和零

class Solution {
public:int findMaxForm(vector<string>& strs, int m, int n) {vector<vector<int>> result(m+1,vector<int> (n+1,0));for(string str:strs){int onenumber = 0,zeronumber = 0;for (char c : str) {if (c == '0') zeronumber++;else onenumber++;}for(int i=m;i>=zeronumber;i--){for(int j=n;j>=onenumber;j--){result[i][j] = max(result[i][j],result[i-zeronumber][j-onenumber]+1);}}}return result[m][n];}};

问题理解

给定一组二进制字符串,每个字符串包含0和1。我们需要选择一些字符串,使得:

  • 所有选中字符串中0的总数不超过 m

  • 所有选中字符串中1的总数不超过 n

  • 选中的字符串数量尽可能多

动态规划思路

1. 状态定义

dp[i][j] 表示:使用最多 i 个0和 j 个1时,能够组成的最大字符串数量

2. 状态转移

对于每个字符串,我们有两种选择:

  • 不选这个字符串dp[i][j] 保持不变

  • 选这个字符串dp[i][j] = dp[i - zeros][j - ones] + 1

状态转移方程:

cpp

dp[i][j] = max(dp[i][j], dp[i - zeros][j - ones] + 1);

3. 为什么从后往前遍历?

这是0-1背包问题的核心技巧:

  • 从后往前遍历:确保每个字符串只被使用一次(避免重复选择)

  • 如果从前往后遍历,会变成完全背包问题(每个物品可以选多次)

4. 具体步骤

  1. 初始化:创建 (m+1) × (n+1) 的二维数组,初始值为0

  2. 遍历每个字符串

    • 计算当前字符串的0和1的数量

    • 从 m 到 zeros,从 n 到 ones 反向更新dp表

  3. 返回结果dp[m][n] 就是最大数量

示例说明

假设 strs = ["10", "0001", "111001", "1", "0"]m = 5n = 3

对于字符串 "10":

  • zeros = 1, ones = 1

  • 更新所有 i >= 1 且 j >= 1 的位置

对于字符串 "0001":

  • zeros = 3, ones = 1

  • 更新所有 i >= 3 且 j >= 1 的位置

以此类推...

时间复杂度

  • 外层循环:O(S),S为字符串数量

  • 内层循环:O(M × N)

  • 总复杂度:O(S × M × N)

空间复杂度

  • O(M × N),即dp表的大小

这种解法巧妙地利用了动态规划和背包问题的思想,通过反向遍历确保每个字符串只被考虑一次,从而找到最优解。

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

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

相关文章

图神经网络介绍

源自论文&#xff1a;Survey on Graph Neural Networks 图神经网络&#xff08;GNNs&#xff09;中的符号与定义详解 本文使用了图论和深度学习领域的标准符号体系&#xff0c;以确保对图结构数据的描述清晰一致。以下是核心符号和定义的详细说明&#xff1a; 一、基础图结构符…

测试报告:“问卷考试系统”项目

目录 一、报告概述 &#xff08;一&#xff09;项目背景 &#xff08;二&#xff09;项目核心模块与测试目的 1、项目核心模块 2、测试目的 &#xff08;三&#xff09;测试环境 1、硬件环境 2、软件环境 &#xff08;1&#xff09;操作系统 &#xff08;2&#xff0…

Linux笔记---网络计算器

1. 网络程序分层 我们说过&#xff0c;OSI7层模型十分完美&#xff0c;但是因特网实际上采用的是TCP/IP五层模型&#xff1a; 实际上&#xff0c;对比可以发现&#xff0c;TCP/IP模型实际上就是将OSI的前三层模型合并为了应用层。 这就提示我们&#xff0c;我们设计的应用程…

《智能网联汽车交通仿真软件可信度评估》团标启动会圆满举办

让数据真正闭环的L4级自动驾驶仿真工具链&#xff0d;杭州千岑智能科技有限公司&#xff1a;RSim 近日&#xff0c;由中国仿真学会主办、清华大学牵头的《智能网联汽车交通仿真软件可信度评估》团体标准启动会在北京成功举行。杭州千岑科技有限公司作为智能网联汽车测试验证领域…

关于 MCU 芯片外围电路的快速入门介绍

MCU&#xff08;微控制单元&#xff0c;Microcontroller Unit&#xff09;是嵌入式系统的“大脑”&#xff0c;但需通过外围电路实现供电、信号输入/ 输出、通信、存储等功能&#xff0c;才能构成完整的工作系统。外围电路的设计直接决定 MCU 的稳定性、功能扩展性和适用场景&a…

Uniapp onLoad 和 onShow 区别

一、核心区别生命周期触发时机执行次数参数获取onLoad页面首次创建时触发仅1次支持获取URL参数optionsonShow页面每次显示时触发&#xff08;包括返回&#xff09;多次无法获取URL参数二、实战数据请求场景优先使用onLoad请求数据的场景&#xff1a;初始化数据当需要根据URL参数…

大模型预训练评估指标

模型效果评测 关于 Language Modeling 的量化指标&#xff0c;较为普遍的有 [PPL]&#xff0c;[BPC]等,可以简单理解为在生成结果和目标文本之间的 Cross Entropy Loss 上做了一些处理&#xff0c;这种方式可以用来评估模型对「语言模板」的拟合程度即给定一段话&#xff0c;预…

【Matlab】-- 机器学习项目 - 基于XGBoost算法的数据回归预测

文章目录 文章目录01 内容概要02 部分代码03 代码解读04 运行结果05 基于XGBoost算法的数据回归预测源码01 内容概要 XGBoost属于集成学习中的Boosting方法&#xff0c;其基本思想是&#xff1a; 逐步构建多个弱学习器&#xff08;通常是CART决策树&#xff09;&#xff0c;每…

Memory in LLM Agent

Memory in LLM Agent 1 为什么需要“记忆” —— 背景与动机 在构建 LLM Agent&#xff08;Large Language Model Agent&#xff0c;大语言模型驱动的智能体&#xff09;的过程中&#xff0c;“记忆”&#xff08;Memory&#xff09;是一个绕不开的核心问题。没有记忆的 Agent…

三甲地市级医院数据仓湖数智化建设路径与编程工具选型研究(上)

摘要 本研究旨在探索三甲地市级医院数据仓湖数智化建设的实施路径与工具选型策略,以响应国家《"十四五"全民健康信息化规划》中2025年医疗数据平台联通全覆盖的政策要求,同时解决地市级医院面临的资源限制(年均信息化投入占总营收1.5%)、区域协同需求突出及多业…

25.9.10_CTF-reverse_RC4那些事儿

CTF-reverse_RC4那些事儿 0x00 RC4加密知识点 推荐看这位up主的视频https://www.bilibili.com/video/BV1G64y1Y7p4/?spm_id_from333.1391.0.0&p2 简单来说RC4算法包括两部分KSA(利用Key生成S盒)和PRGA(利用S盒生成密钥流): KSA: 初始化S&#xff08;一般是0-255&…

网络编程(6)

【0】复习 Modbus&#xff1a;modbus tcp modbus rtu Modbus TCP: 特点&#xff1a;主从问答&#xff08;控制 采集信息&#xff09; 应用层协议&#xff08;基于TCP通信&#xff09;、默认端口502 组成&#xff1a;报文头&#xff08;7 事物2 协议2 长度2 单元表示1&#xff…

技术文章大纲:AI绘画—动漫角色生成赛

技术文章大纲&#xff1a;AI绘画—动漫角色生成赛 背景与意义 动漫角色生成赛的兴起与发展AI绘画技术在动漫创作中的应用价值比赛对推动AI艺术创新的作用 技术核心&#xff1a;AI绘画模型 主流模型介绍&#xff08;如Stable Diffusion、MidJourney、DALLE&#xff09;针对动…

Flink-新增 Kafka source 引发状态丢失导致启动失败

背景 Flink Job 新增 kafka source 算子,从状态保留并启动后提示 org.apache.flink.util.StateMigrationException: The new state typeSerializer for operator state must not be incompatible,导致任务 Fail。 Source: task-kafka-source -> task-kafka-transform (1…

【系统架构设计(26)】系统可靠性分析与设计详解:构建高可用软件系统的核心技术

文章目录一、本文知识覆盖范围1、概述2、知识体系概览二、系统可靠性基础概念1、可靠性与可用性的本质区别2、软件可靠性与硬件可靠性的深度对比3、核心可靠性指标的业务价值三、系统架构可靠性模型1、串联系统的可靠性挑战2、并联系统的高可靠性设计3、混合系统的复杂性管理四…

4 C 语言数据结构实战:栈和队列完整实现(结构体 + 函数)+ 最小栈解决方案

栈和队列 1. 栈 栈&#xff1a;⼀种特殊的线性表&#xff0c;其只允许在固定的⼀端进⾏插⼊和删除元素操作。进⾏数据插⼊和删除操作 的⼀端称为栈顶&#xff0c;另⼀端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#xff09;的原则。 压栈&…

Milvus基于docker主机外挂实践

一、安装docker与我之前写的原博客&#xff1a;ubuntu安装milvus向量数据库&#xff0c;获取key不同&#xff0c;原博客获取key已经过时# 更新Ubuntu软件包列表和已安装软件的版本: sudo apt update# 安装Ubuntu系统的依赖包 sudo apt-get install ca-certificates curl gnupg …

使用python test测试http接口

使用python test测试http接口获取token和控制session&#xff0c;后面大多数接口要带上这些信息 import time import requestsfrom common.aes_algorithm import AES from config.config import Config from config.log import logclass Common:username "admin"pas…

平时只会CRUD,没有高质量项目经验,我该怎么办

我没有项目经验怎么办 首先&#xff0c;不管是应届生还是社招几年工作经验的朋友&#xff0c;除非特别厉害的人&#xff0c;大家都会遇到这个问题。 我们该怎么处理&#xff0c;关注hikktn&#xff01;为你解答这个问题。 问AI世面上那个大厂程序员项目推荐 为什么这么说呢&…

网编.hw.9.10

云盘下载#include <myhead.h> #define SER_IP "192.168.108.93" #define SER_PORT 69 #define addr "192.168.109.6" #define port 8888/******************主程序******************/ int main(int argc, const char *argv[]) {//1、创建一个用于通…