当前位置: 首页 > news >正文

元宝 LeetCode 2902. 和带限制的子多重集合的数目 Java实现

这道题是 LeetCode 2902 “Count of Sub-Multisets With Bounded Sum”,属于多重背包问题,需要计算在给定数组nums中,所有元素和位于区间[l, r]内的子多重集合(允许重复元素,但每个元素的选取次数不超过其在nums中的出现次数)的数目。下面给出 Java 实现及其核心思路。

解题思路

  1. 统计频率:用哈希表记录每个数字出现的次数,特别处理数字0(因为0不影响和,但会影响方案数)。

  2. 动态规划:定义dp[j]表示元素和恰好为j的子多重集合的方案数。初始时dp[0] = 1(空集合)。

  3. 多重背包转移:对于每个非零数字num及其出现次数cnt,采用“前缀和优化”的转移方式:

    • 先计算stride[i] = dp[i] + dp[i-num] + dp[i-2*num] + …(即不考虑次数上限时的方案数)。

    • 再通过dp[i] = stride[i] - stride[i - (cnt+1)*num]扣除选取超过cnt次的方案。

  4. 累加答案:最后将dp[l]dp[r]的所有方案数相加,并乘以(零的个数 + 1)(因为0可以任意选或不选)。

Java 实现

import java.util.*; class Solution { private static final int MOD = 1_000_000_007; public int countSubMultisets(List<Integer> nums, int l, int r) { // 1. 统计频率 Map<Integer, Integer> count = new HashMap<>(); for (int num : nums) { count.put(num, count.getOrDefault(num, 0) + 1); } // 2. 处理数字 0 int zeros = count.getOrDefault(0, 0); count.remove(0); // 3. 动态规划数组 int[] dp = new int[r + 1]; dp[0] = 1; // 4. 多重背包转移 for (Map.Entry<Integer, Integer> entry : count.entrySet()) { int num = entry.getKey(); int freq = entry.getValue(); // 计算 stride[i] = dp[i] + dp[i-num] + dp[i-2*num] + ... int[] stride = dp.clone(); for (int i = num; i <= r; i++) { stride[i] = (stride[i] + stride[i - num]) % MOD; } // 扣除超过 freq 次的方案 int limit = num * (freq + 1); for (int i = r; i >= 0; i--) { if (i >= limit) { dp[i] = (stride[i] - stride[i - limit] + MOD) % MOD; } else { dp[i] = stride[i] % MOD; } } } // 5. 累加区间 [l, r] 的方案数 long total = 0; for (int i = l; i <= r; i++) { total = (total + dp[i]) % MOD; } // 6. 乘以零的贡献(每个零可选可不选) return (int) (total * (zeros + 1) % MOD); } }

关键点说明

  • 时间复杂度:O(n + r·√Σ(nums[i])),其中 n 为数组长度,r 为上限值。

  • 空间复杂度:O(r),仅使用一维 DP 数组。

  • 零的处理:数字0不参与和的计算,但每个0都可以独立地“选”或“不选”,因此最终答案需乘以(zeros + 1)

  • 模运算:由于结果可能很大,需要在每次加法、减法后取模1_000_000_007

示例

输入:nums = [1,2,2,3], l = 3, r = 5

输出:7

解释:和位于 [3,5] 的子多重集合有:

  • {1,2}(和=3)

  • {3}(和=3)

  • {1,2,2}(和=5)

  • {2,3}(和=5)

  • {1,3}(和=4)

  • {1,1,2}(和=4,但只有一个1,不可行)← 注意重复元素限制

    实际需根据代码计算得到 7 种。

此实现参考了 LeetCode 官方题解中的多重背包优化方法,在时间和空间上均达到较优水平。

http://www.gsyq.cn/news/1438445.html

相关文章:

  • 元宝 LeetCode 2902. 和带限制的子多重集合的数目 Python3实现
  • 区块链+物联网构建环境价值互联网:机器自主交易绿电与碳资产
  • AMD SEV实战:在KVM/QEMU上快速搭建你的第一个机密虚拟机(含密钥管理避坑指南)
  • 构建面向AI的现代数据湖:从架构原则到硬件选型实战
  • AI Agent Harness冷启动优化:快速响应方案
  • 医疗设备安规入门:一张图搞懂BF型设备的MOOP/MOPP绝缘路径(附GB 9706.1附录解析)
  • 从布尔表达式到可综合代码:一个全加器的Verilog RTL设计完整流程(附代码规范检查清单)
  • 从DDR到DDR5:Burst和Prefetch的演变如何决定了内存性能的飞跃
  • DIY土壤湿度传感器:从腐蚀铜板到Arduino读取的完整指南
  • 量子策略评估(QPE)原理与强化学习应用
  • 别再只用if了!用np.all()和np.any()让你的NumPy数据清洗效率翻倍
  • Nacos 2.x 本地联调踩坑记:解决 gRPC 端口偏移导致的 StatusRuntimeException
  • 从呼吸到电能:DIY口罩发电项目详解与能量收集技术实践
  • 基于Arduino与步进/伺服电机的低成本物理开关自动化方案
  • AI时代人类转型:从执行者到策展人与教练的核心能力重构
  • AI营销实战指南:从用户画像到智能投放的完整落地路径
  • CRAFT框架:大模型驱动的多机器人协作训练方案
  • GPT模型技术本质与AGI鸿沟:从Transformer到通用人工智能的路径分析
  • 别再手动敲字了!用Python+Tesseract批量提取图片文字,5分钟搞定文档电子化
  • 量子信息流安全:SPO-QPN框架下的并发系统不透明性验证与策略强制执行
  • AI诗歌创作实验:从提示词工程到人机协作的实践指南
  • 用Python和PySAL搞定空间数据分析:手把手教你绘制乔治亚州教育不平等热点图
  • 别再对着真机发愁了!用华为eNSP从零搭建你的第一个企业网实验环境(附拓扑文件)
  • 2023年AR技术趋势:从空间计算到WebAR,12个实战方向深度解析
  • 避坑指南:STM32的PWM输入捕获模式,配置TIM3_CH1时这几个寄存器别设错
  • 别再手动发通知了!用ThinkPHP 6.x + uni-push 2.0 给你的UniApp APP做个自动消息推送服务
  • 2024年Intel OneAPI更新后,VASP 6.3.2安装避坑全记录(附常见错误解决方案)
  • CTF流量分析实战:从一道DNS题看Base64隐写与数据提取(Wireshark操作指南)
  • 不只是点云分割:拆解PMF论文里的多传感器融合思路,以及如何用SemanticKITTI API玩转可视化
  • 反哺RAG,SkillGraph把skill组装起来了