题目:
一个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<n;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"<<endl;
int sum=0;
for(int i=0;i<n;i++)
sum+=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<<getmin(a,7,4)<<endl;
system("pause");
return 0;
}