news 2026/5/23 16:32:54

(100分)- 等和子数组最小和(Java JS Python)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
(100分)- 等和子数组最小和(Java JS Python)

(100分)- 等和子数组最小和(Java & JS & Python)

题目描述

给定一个数组nums,将元素分为若干个组,使得每组和相等,求出满足条件的所有分组中,组内元素和的最小值。

输入描述

第一行输入 m
接着输入m个数,表示此数组nums
数据范围:1<=m<=50, 1<=nums[i]<=50

输出描述

最小拆分数组和

用例
输入7
4 3 2 3 5 2 1
输出5
说明

可以等分的情况有:

4 个子集(5),(1,4),(2,3),(2,3)

2 个子集(5, 1, 4),(2,3, 2,3)

但最小的为5。

题目解析

题目要求我们求解最小拆分数组和,本质上就是寻找最小子集和,也就是确定最大的k值。因为k值越大,对应的子集和就越小。

k值的求解思路如下:

  1. 首先考虑k的上限。当数组所有元素相等时,k等于数组长度m,即每个元素都能独立构成一个子集。因此可以从k=m开始尝试。
  2. 如果k=m不满足条件,就逐步减小k值(k--),直到k=1为止。
  3. 验证数组能否划分为k个和相等的子集,就是判断nums是否能分成k个等和子集。
JavaScript算法源码
/* JavaScript Node ACM模式 控制台输入获取 */ const readline = require("readline"); const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); const lines = []; rl.on("line", (line) => { lines.push(line); if (lines.length === 2) { const m = parseInt(lines[0]); const arr = lines[1].split(" ").map(Number); console.log(getResult(arr, m)); lines.length = 0; } }); function getResult(arr, m) { const sum = arr.sort((a, b) => b - a).reduce((p, c) => p + c); while (m) { if (canPartitionMSubsets([...arr], sum, m)) return sum / m; m--; } return sum; } function canPartitionMSubsets(arr, sum, m) { if (sum % m !== 0) return false; const subSum = sum / m; if (subSum < arr[0]) return false; while (arr[0] === subSum) { arr.shift(); m--; } const buckets = new Array(m).fill(0); return partition(arr, 0, buckets, subSum); } function partition(arr, index, buckets, subSum) { if (index === arr.length) return true; const select = arr[index]; for (let i = 0; i < buckets.length; i++) { if (i > 0 && buckets[i] === buckets[i - 1]) continue; if (select + buckets[i] <= subSum) { buckets[i] += select; if (partition(arr, index + 1, buckets, subSum)) return true; buckets[i] -= select; } } return false; }
Java算法源码

41行在用例

5

5 5 5 5 5

时会出现越界异常

import java.util.LinkedList; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int m = sc.nextInt(); LinkedList<Integer> link = new LinkedList<>(); for (int i = 0; i < m; i++) { link.add(sc.nextInt()); } System.out.println(getResult(link, m)); } public static int getResult(LinkedList<Integer> link, int m) { link.sort((a, b) -> b - a); int sum = 0; for (Integer ele : link) { sum += ele; } while (m > 0) { LinkedList<Integer> link_cp = new LinkedList<>(link); if (canPartitionMSubsets(link_cp, sum, m)) return sum / m; m--; } return sum; } public static boolean canPartitionMSubsets(LinkedList<Integer> link, int sum, int m) { if (sum % m != 0) return false; int subSum = sum / m; if (subSum < link.get(0)) return false; // while (link.get(0) == subSum) { // 此段代码可能越界 while (link.size() > 0 && link.get(0) == subSum) { link.removeFirst(); m--; } int[] buckets = new int[m]; return partition(link, 0, buckets, subSum); } public static boolean partition(LinkedList<Integer> link, int index, int[] buckets, int subSum) { if (index == link.size()) return true; int select = link.get(index); for (int i = 0; i < buckets.length; i++) { if (i > 0 && buckets[i] == buckets[i - 1]) continue; if (select + buckets[i] <= subSum) { buckets[i] += select; if (partition(link, index + 1, buckets, subSum)) return true; buckets[i] -= select; } } return false; } }
Python算法源码
# 输入获取 m = int(input()) link = list(map(int, input().split())) # 算法入口 def getResult(link, m): link.sort(reverse=True) sumV = 0 for ele in link: sumV += ele while m > 0: if canPartitionMSubsets(link[:], sumV, m): return int(sumV / m) m -= 1 return sumV def canPartitionMSubsets(link, sumV, m): if sumV % m != 0: return False subSum = sumV / m if subSum < link[0]: return False while len(link) > 0 and link[0] == subSum: link.pop(0) m -= 1 buckets = [0] * m return partition(link, 0, buckets, subSum) def partition(link, index, buckets, subSum): if index == len(link): return True select = link[index] for i in range(len(buckets)): if i > 0 and buckets[i] == buckets[i - 1]: continue if select + buckets[i] <= subSum: buckets[i] += select if partition(link, index + 1, buckets, subSum): return True buckets[i] -= select return False # 算法调用 print(getResult(link, m))
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/20 17:41:05

(100分)- 端口合并(Java JS Python)

(100分)- 端口合并&#xff08;Java & JS & Python&#xff09;题目描述有M个端口组(1<M<10)&#xff0c; 每个端口组是长度为N的整数数组(1<N<100)&#xff0c; 如果端口组间存在2个及以上不同端口相同&#xff0c;则认为这2个端口组互相关联&#xff0c;…

作者头像 李华
网站建设 2026/5/20 13:01:12

《深入理解Java虚拟机》| 运行时数据区与OOM异常

摘要&#xff1a;本文系统解析《深入理解Java虚拟机》中的运行时数据区与OOM异常&#xff0c;包括程序计数器、虚拟机栈、堆内存、方法区与直接内存&#xff0c;同时讲解OOM异常等解决方案。 书摘内容 运行时数据区域 运行时数据区是 JVM 的内存核心&#xff0c;分为线程共享区…

作者头像 李华
网站建设 2026/5/21 14:51:34

leetcode 925. Long Pressed Name 长按键入-耗时100

Problem: 925. Long Pressed Name 长按键入 耗时100%&#xff0c;双指针&#xff0c;若左右字符相等l; r&#xff0c;若r > 0 && typed[r-1]typed[r]则r&#xff0c;否则false&#xff0c;最后若while(r < n2 && typed[r-1]typed[r]) r;&#xff0c;if(l…

作者头像 李华
网站建设 2026/5/23 6:46:08

如何获得Agentic AI提示工程架构师认证?备考与实战经验

Agentic AI提示工程架构师认证全攻略&#xff1a;备考计划实战经验核心技巧 1. 标题 (Title) 从入门到持证&#xff1a;Agentic AI提示工程架构师认证备考实战指南Agentic AI提示工程架构师认证之路&#xff1a;我如何3个月从零基础到通过考试&#xff1f;成为AI架构师的敲门…

作者头像 李华
网站建设 2026/5/23 10:22:47

14.僵尸孤儿-进程状态

一个pcb既属于全局链表又属于这个队列这个队列也是双链表&#xff0c;只不过先进先出FIFO运行状态就是正在被cpu运行&#xff0c;或者准备好了随时等待被调度。 包括运行和就绪。一个进程要去读键盘就要转去另一个队列&#xff0c;如果这个设备没有活跃&#xff0c;就没有读到键…

作者头像 李华