使用贪心+动态规划思想求解“最小服务器数量”问题(幂次数组组合和)

浅宇同学_9986

浅宇同学_9986

2026-10-06

138人浏览

原创

 使用贪心+动态规划思想求解“最小服务器数量”问题(幂次数组组合和)

给定一个目标负载值和一个由2的幂组成的服务器容量数组(如 [1, 2, 4, 8, …]),求最少需选用几个服务器,使其容量之和恰好等于目标负载;若无解则返回 -1。该问题本质是带约束的「最少硬币数」变体,可借助记忆化递归高效求解。

给定一个目标负载值和一个由2的幂组成的服务器容量数组(如 [1, 2, 4, 8, …]),求最少需选用几个服务器,使其容量之和**恰好等于**目标负载;若无解则返回 -1。该问题本质是带约束的「最少硬币数」变体,可借助记忆化递归高效求解。

这是一个经典的最小组合数凑和问题,但具有关键特殊性:输入数组中所有元素均为 2 的幂(即 1, 2, 4, 8, 16, ...),且每个服务器可重复使用(题干中“server[1] 和 server[3]”暗示索引可复用,结合示例 getMinServers(10, [1, 1, 2, 4, 8, 16]) → 2 可验证:2 + 8 = 10,对应两个服务器)。注意:虽然数组含重复值(如两个 1),但题目逻辑上更倾向将其视为无限供应的面额集合——因为若仅限单次使用,[1, 1, 2, 4, 8] 中 10 = 2 + 8 已成立,无需依赖重复 1;而算法设计也默认允许重复选取同一值(递归中 include 分支调用 findMinServers(load - _array[index], index) 而非 index + 1,明确表示可重复使用当前元素)。

✅ 正确解法:记忆化递归(DFS + 剪枝)

暴力枚举所有子集或嵌套循环(如两层 for)仅适用于固定数量选择(如“恰好选2个”),但本题要求最小数量不限,必须支持 1 个、2 个、3 个……直至全覆盖。因此,推荐采用自顶向下的记忆化搜索:

  • 状态定义:findMinServers(remain, idx) 表示用 arr[idx..end] 中的元素(可重复)凑出剩余负载 remain 所需的最少服务器数;
  • 选择策略:
    • ✅ 包含当前元素:1 + findMinServers(remain - arr[idx], idx) —— 使用它,并可再次使用它(idx 不递增);
    • ✅ 排除当前元素:findMinServers(remain, idx + 1) —— 跳过它,尝试下一个;
  • 边界条件:
    • remain === 0 → 成功,返回 0(无需更多服务器);
    • remain → 失败,返回 <code>-1;
  • 合并结果:取两种选择中有效解的最小值(注意 -1 的空值处理)。

⚠️ 关键细节:原答案中 _array.sort((a, b) => b - a) 为降序排列,虽不影响正确性,但非必需。由于 2 的幂天然有序,且算法本身不依赖顺序,升序或降序均可。但降序可能略微提升剪枝效率(大数优先尝试,更快触达 remain )。

以下是优化后的完整实现(含记忆化,避免指数级重复计算):

function getMinServers(expected_load, servers) {
    // 去重并升序排序(更符合直觉,且便于后续扩展)
    const uniqueServers = [...new Set(servers)].sort((a, b) => a - b);

    // 记忆化缓存:Map
    const memo = new Map();

    function dfs(remain, idx) {
        // 边界检查
        if (remain === 0) return 0;
        if (remain = uniqueServers.length) return -1;

        const key = `${remain},${idx}`;
        if (memo.has(key)) return memo.get(key);

        const curr = uniqueServers[idx];
        const include = dfs(remain - curr, idx); // 重复使用当前服务器
        const exclude = dfs(remain, idx + 1);     // 跳过当前服务器

        let result;
        if (include === -1 && exclude === -1) {
            result = -1;
        } else if (include === -1) {
            result = exclude;
        } else if (exclude === -1) {
            result = include + 1;
        } else {
            result = Math.min(include + 1, exclude);
        }

        memo.set(key, result);
        return result;
    }

    return dfs(expected_load, 0);
}

// 测试用例
console.log(getMinServers(10, [1, 1, 2, 4, 8, 16])); // 输出: 2 (2 + 8)
console.log(getMinServers(7, [1, 2, 4]));            // 输出: 3 (1 + 2 + 4)
console.log(getMinServers(3, [2]));                 // 输出: -1 (无法凑出)

? 为什么不能用贪心?(重要辨析)

你可能直觉想到“从最大服务器开始贪心选取”,例如 10 → 选 8,剩 2 → 选 2,共 2 台。在纯 2 的幂集合(如 [1,2,4,8,...])下,贪心确实最优——这等价于整数的二进制拆分(每个数有唯一二进制表示,1 的个数即最少服务器数)。但本题数组含重复值(如 [1,1,2,4,8])且未声明“无限供应”,严格来说属于有界硬币问题。然而,示例 getMinServers(10, [1, 1, 2, 4, 8, 16]) 返回 2,证实了 8+2 合法,说明至少有两个 2 或 2 可复用。因此,题目隐含“每个容量值无限供应”,此时贪心成立,但面试中建议仍用通用 DP 解法体现工程严谨性。

✅ 总结

  • 核心洞察:问题 = 无限硬币找零的最小硬币数,面额为 2 的幂;
  • 最优解法:记忆化 DFS,时间复杂度 O(L × N)(L 为 expected_load,N 为去重后服务器种类数);
  • 避坑提示:勿用多层 for 循环(仅支持固定长度组合);勿忽略 remain === 0 的终止条件;务必处理 -1 的传播逻辑;
  • 进阶思考:若服务器数量有限(如每个容量最多用一次),则需转为 0-1 背包变体,状态改为 dp[i][w] = min servers using first i types to make w。

掌握此模型,即可从容应对各类“最小组合数凑目标值”面试题。

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
服务器是什么
服务器是什么

服务器是一种计算机硬件设备或软件程序,它具有强大的计算和存储能力,用请求、存储数据和提供服务。它在互联网中着关重要的作用,为用户提供各种服务和资源。本专题为大家提供服务器相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.15

437

5

连接apple id服务器时出错
连接apple id服务器时出错

连接apple id服务器时出错的原因包括网络连接问题、服务器问题、Apple ID账户问题、设备问题、防火墙或安全软件问题、时间和日期设置问题、Apple服务器维护等。本专题为大家提供apple id相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.08

880

5

搭建互联网服务器
搭建互联网服务器

搭建互联网服务器需要:1、选择合适的硬件和操作系统,第一步是选择合适的硬件和操作系统;2、安装和配置操作系统,是搭建互联网服务器的关键步骤;3、安装和配置服务器软件,是搭建互联网服务器的下一步,常见的服务器软件包括Apache、Nginx、Tomcat等;4、配置防火墙和安全性,是搭建互联网服务器的重要步骤;5、域名解析和配置,是搭建互联网服务器的最后一步。

2023.09.19

2692

5

如何查看服务器状态
如何查看服务器状态

查看服务器状态的方法有使用命令行工具、图形界面工具、监控工具、日志文件和远程管理工具等。本专题为大家提供服务器状态相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.09

896

5

服务器域名转接慢怎么解决
服务器域名转接慢怎么解决

服务器域名转接慢的解决办法有DNS优化、服务器优化、CDN加速、前端优化和网络优化等。本专题为大家提供服务器相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.17

809

5

服务器评测软件
服务器评测软件

服务器评测软件有PassMark Software、CPU-Z、GPU-Z、CrystalDiskMark、IOmeter、JMeter、LoadRunner、Apache Bench等等。详细介绍:1、PassMark Software是一款综合性的服务器性能测试软件,可以评估服务器在各种负载条件下的性能;2、CPU-Z是一款可以提供服务器CPU详细信息的软件等等。

2023.10.17

414

3

如何开启TFTP服务器
如何开启TFTP服务器

开启TFTP服务器的步骤包括选择TFTP服务器软件、下载和安装软件、配置TFTP服务器以及启动和测试服务器等。本专题为大家提供服务器相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.18

2436

4

服务器负载不兼容怎么解决
服务器负载不兼容怎么解决

解决方法:1、增加服务器资源;2、负载均衡;3、优化应用程序;4、增加缓存机制;5、分布式架构;6、限流和熔断;7、自动化扩容。想知道更详细服务器负载不兼容的解决方法,可以访问本专题下面的文章。

2023.10.20

4512

4

宽带如何接入服务器
宽带如何接入服务器

宽带接入服务器的方法有ADSL宽带接入服务器、光纤接入服务器、无线接入服务器和以太网接入服务器等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.20

727

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.6万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.4万人学习