将数组分成m个子数组,使子数组和的最大值最小

题目:

一个int型数组,数组元素代表每件事工人工作时长,现有m个工人,这些工人可以同时工作,问最短多久工作可以完成


解题思路:

逆向思维,先将所有数组总和sum求出,然后看sum/2的g工作时长由几个工人同时可以完成,如果需要的人数小于设定,每人可以用时更少,然后选

sum/2/2在比,如果需要的人数大于设定,每人用时要更多,要在sum/2~sum中二分。以此类推,利用二分查找法,即可找到最小的那个

JAVA程序:

public static int solution3(int[] arr, int num) {
if (arr == null || arr.length == 0 || num < 1) {
throw new RuntimeException("err");
}
if (arr.length < num) {
int max = Integer.MIN_VALUE;
for (int i = 0; i != arr.length; i++) {
max = Math.max(max, arr[i]);
}
return max;
} else {
int minSum = 0;
int maxSum = 0;
for (int i = 0; i < arr.length; i++) {
maxSum += arr[i];
}
while (minSum != maxSum - 1) {
int mid = (minSum + maxSum) / 2;
if (getNeedNum(arr, mid) > num) {
minSum = mid;
} else {
maxSum = mid;
}
}
return maxSum;
}
}


public static int getNeedNum(int[] arr, int lim) {
int res = 1;
int stepSum = 0;
for (int i = 0; i != arr.length; i++) {
if (arr[i] > lim) {
return Integer.MAX_VALUE;
}
stepSum += arr[i];
if (stepSum > lim) {
res++;
stepSum = arr[i];
}
}
return res;
}


public static int[] generateRandomArray(int length) {
int[] result = new int[length];
for (int i = 0; i != result.length; i++) {
result[i] = (int) (Math.random() * 10) + 1;
}
return result;
}


public static void printArray(int[] arr) {
for (int i = 0; i != arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}


public static void main(String[] args) {
int[] arr = generateRandomArray(300);
int painterNum = 2;
System.out.println(solution1(arr, painterNum));
System.out.println(solution2(arr, painterNum));
System.out.println(solution3(arr, painterNum));


arr = generateRandomArray(5000000);
painterNum = 20000;
long start = System.currentTimeMillis();
System.out.println(solution3(arr, painterNum));
long end = System.currentTimeMillis();
System.out.println("cost time: " + (end - start) + " ms");


}


}

C++程序:



int find(int *a,int n,int lim)
{
int count=1;
int sum=0;
for(int i=0;i{
if(a[i]>lim)
return INT_MAX;
else
{
            sum+=a[i];
  if(sum>lim)
  {
sum=a[i];
count++;
  }
}



}
return count;
}
int getmin(int *a,int n,int m)
{
if(a==NULL||n==0||m==0)
cout<<"error"<

int sum=0;
for(int i=0;isum+=a[i];


int min=0;
int max=sum;

while(min!=max-1)
{
 int mid=(min+max)/2;
 if(find(a,n,mid)>m)
  min=mid;
 else
  max=mid;
}

return max;




}


int main()
{
int a[]={3,2,4,5,2,7,1};
   cout<
system("pause");
return 0;
}


你可能感兴趣的:(将数组分成m个子数组,使子数组和的最大值最小)