Daily LC:数组均分
描述:一个整数数组,长度为n,将其分为m份,使各份的和相等,求m的最大值
case:比如{3,2,4,3,6} 可以分成
{3,2,4,3,6} m=1;
{3,6}{2,4,3} m=2
{3,3}{2,4}{6} m=3 所以m的最大值为3
思路分析:
隐性要求:total%m==0,且m的取值范围为1<m<=n;
求m的最大值,则让m从n开始递减,找到第一个符合条件的m返回即可,如果没有则返回1。
设数组为nums,数组的和为sum,设一临时数组store来存储分组情况,groupId表示分组编号store[i]=1,则说明a[i]分在第一组。
当sum%m!=0时,表示无法均分,直接跳过;
当sum%m==0时,遍历数组中每个元素,若当前元素状态为未分配,即store[i]=0,将其分配到相应组中,并基于分配状态进行结果判断:
a.若组内元素和>sum/m,则说明当前元素无法加入,令store[i]=0;
b.若组内元素和=sum/m,则令groupId++,继续遍历,判断下一组;
c.若组内元素和<sum/m,则将当前元素加入该组,状态改为已选,store[i]=组号,继续进行下一个元素的判断;
代码:
public class Main { public static void main(String[] args) { int[] nums=new int[]{3,2,4,3,6}; System.out.println(maxPartition(nums)); } static int maxPartition(int[] nums){ int n=nums.length; if(n<=1){ return n; } int sum=0; for(int num:nums){ sum+=num; } int[] store=new int[n]; for(int m=n;m>=2;m--){ if(sum%m!=0){ continue; } for(int i=0;i<n;i++){ store[i]=0; } if(tryPartition(nums,n,m,sum,sum/m,store,sum/m,1)){ return m; } } return 1; } static boolean tryPartition(int[] nums,int n,int m,int sum,int groupSum,int[]store,int goal,int groupId){ if(goal<0){ return false; } if(goal==0){ groupId++; goal=groupSum; if(groupId==m+1){ return true; } } for(int i=0;i<n;i++){ if(store[i]!=0){ continue; } store[i]=groupId; if(tryPartition(nums,n,m,sum,groupSum,store,goal-nums[i],groupId)){ return true; }else{ store[i]=0; } } return false; } }