交换两个数组的元素,使两个数组和的差最小
来源:互联网 发布:mac怎么隐藏硬盘文件 编辑:程序博客网 时间:2024/05/22 08:25
前些时候面试碰到的题目:有两个有序正整数数组array1[N]、array2[M],通过交换两数组的元素,使两个数组的和最接近。
基本算法思路:
每次从array1、array2选择出一对能使交换后得array1和与array2和的差值变小的组合array1[i]、array2[j]作交换;直到对任意组合array1[i]、array2[j]作交换,array1和与array2和的差值都无法变得更小,算法即结束。
网上查了下,基本有两种算法:
(1) 暴力算法:采用双重循环取逐一比较组合array1[i]、array2[j],只要交换能让array1和与array2和的差值变小,即进行交换;直到算法结束。
(2) 贪心算法:采用双重循环逐一比较取组合,找到交换后能让array1和与array2和的差值变得最小的组合array1[i]、array2[j],才进行交换;直到算法结束。
上面的贪心算法中为寻找最优组合,采用双重循环逐一比较,算法时间复杂度最好也只有O(N*M) ( 若N=M即(N^2) )。自己琢磨了一段时间,同样采用贪心算法,发现寻找最优组合的算法时间复杂度可以达O(N+M) ( 若N=M即(N) ),下面是相关分析:
假设sum(array1) > sum(array2):
当前数组array1和数组aarray2的和之差为:
A = sum(array1) - sum(array2)
对组合array1[i]、array2[j],交换后,array1与array2的和之差为:
A' = sum(array1) - array1 [i] + array2 [j] - (sum(array2) - array2 [j] + array1 [i])
= sum(array1) - sum(array2) - 2 (array1 [i] - array2 [j])
= A - 2 (array1 [i] - array2 [j])
设x = array1[i] - array2 [j]
最优组合即为使得x最接近A/2的一对array1[i]、array2[j]组合。
我给出的寻找最优组合的算法思路:
首先,将i,j初始化为0,
若当前array1[i] - array2 [j]> A/2,即array2 [j]偏小;执行操作j++ 再进行比较;
若当前array1[i] - array2 [j]< A/2,即array2 [i]偏小;执行操作i++ 再进行比较;
直到i=N-1,j=M-1,算法时间复杂度为O(N+M)。
举例分析:
Array1[LENGTH2]={7, 15, 18, 23, 38,42} sum(array1)= 143
Array2[LENGTH1]={ 3,12,16, 27, 29, 35} sum(array2)= 122
A = sum(array1) - sum(array2)= 21
A/2 = 10.5
需要找一组合array1[i]、array2[j],array1[i] - array2[j] 最接近10.5
第一次比较array1[ 0 ] - array2[ 0 ] = 4 < 10.5 然后i++
第二次比较array1[ 1 ] - array2[ 0 ] = 12 > 10.5然后j++
第三次比较array1[1 ] - array2[ 1 ] = 3 > 10.5然后j++
…….
如下图所示,总共最多进行了11次比较。
与双重循环取逐一比较相比可以发现:双重循环取逐一比较中很多的比较都是多余的,因为对升序数组:
如果array1[ 0 ] - array2[ 0 ] = 4 < 10.5
必有array1[ 0 ] - array2[ 1 ] < array1[ 0 ] - array2[ 0 ] = 4 < 10.5
即与array1[ 0 ] 、array2[ 0 ]相比array1[ 0 ] - array2[ 1 ]绝不是更好的组合
所以接着只需对i++ 即array1[ 1 ] - array2[ 0 ] 与10.5 进行比较
如果array1[ 1 ] - array2[ 0 ] = 12 > 10.5
必有array1[ 2 ] - array2[ 0 ] > array1[ 1 ] - array2[ 0 ] = 12 > 10.5
即与array1[ 2 ] 、array2[ 0 ]相比array1[ 1 ] - array2[ 0 ]绝不是更好的组合
所以接着只需对j++ 即array1[ 1 ] - array2[ 1 ] 与10.5 进行比较
附带C源码:
#include<stdio.h>
#include<math.h>
#define LENGTH1 8
#define LENGTH2 8
int endflag=0;
int ksort(int *array,int temp,int length,int j) //用temp替换array[j],并将数组排序
{
int k=j;
while( k>0&&array[k-1]>temp )
{
array[k] = array[k-1];
k--;
}
while(( k<length-1)&&(array[k+1]<temp) )
{
array[k] = array[k+1];
k++;
}
array[k] = temp;
return 0;
}
int mini_tmp(int *min_i , int *min_j , int *min_temp, int now_temp, int i, int j) //如果当前组合比最优组合更好,则重置最优组合
{
if( (*min_temp) > now_temp)
{
*min_i = i;
*min_j = j;
*min_temp = now_temp;
}
return 0;
}
int kv_change(int *array1,int *sum1,int leng1,int *array2,int *sum2,int leng2,int flag) //sum1<sum2
{
int i,j,k;
int temp = 0,temp1 = *sum2 - *sum1,temp2;
int min_i=0,min_j=0,min_temp = temp1;
for(i=0,j=0;;)
{
if( (j==leng2-1)&&(i==leng1-1) )
{
mini_tmp(&min_i , &min_j , &min_temp, abs( 2*(array2[j]-array1[i]) - temp1 ), i, j);
break;
}
else if( (j==leng2-1)&&(i<leng1-1) )
{
if( abs( 2*(array2[j]-array1[i]) - temp1) < abs( temp1 - 2*(array2[j]-array1[i+1]) ) )
{
mini_tmp(&min_i , &min_j , &min_temp, abs( 2*(array2[j]-array1[i]) - temp1 ), i, j);
break;
}
else
{
i++;
}
}
else if( (j<leng2-1)&&(i==leng1-1) )
{
if( abs( 2*(array2[j]-array1[i]) - temp1 ) < abs( temp1 - 2*(array2[j-1]-array1[i]) ) )
{
mini_tmp(&min_i , &min_j , &min_temp, abs( 2*(array2[j]-array1[i]) - temp1 ), i, j);
break;
}
else
{
j--;
}
}
else
{
mini_tmp(&min_i , &min_j , &min_temp, abs( 2*(array2[j]-array1[i]) - temp1 ), i, j);
if( 2*(array2[j]-array1[i]) < temp1 )
{
j++;
}
else if( 2*(array2[j]-array1[i]) > temp1 )
{
i++;
}
else
{
endflag = 1;
break;
}
}
}
if( 1 )
{
i = min_i;
j = min_j;
temp2 = min_temp;
// printf("min_i = %d ,min_j = %d ,min_temp = %d\n", min_i ,min_j ,min_temp );
// temp2 = abs( temp1 - 2*(array2[j]-array1[i]) );
if(temp2<temp1)
{
if(flag)
{
printf("Exchange array1[%d] = %d ,array2[%d] =%d\n",i,array1[i],j,array2[j]);
}
else
{
printf("Exchange array2[%d] = %d ,array1[%d] =%d\n",i,array1[i],j,array2[j]);
}
temp = array1[i]; //change need to sort
*sum1 = *sum1 + (array2[j]-array1[i]);
*sum2 = *sum2 - (array2[j]-array1[i]);
ksort( array1, array2[j], leng1, i); //sort array1
ksort( array2, temp, leng2, j); //sort array2
}
else // the end,no need to change anymore
{
endflag = 1;
}
}
return 0;
}
int main(void)
{
int array1[LENGTH1]={7, 15, 18, 23, 38,42,57,64},array2[LENGTH2]={ 3,12,16, 27, 29, 35,43,50};
int i,j,k;
int temp = 0,temp1 = 0,temp2 = -1;
int sum1=0,sum2=0;
for(i=0;i<LENGTH1;i++)
{
sum1+=array1[i];
printf("%d ",array1[i]);
}
printf("\n");
for(j=0;j<LENGTH2;j++)
{
sum2+=array2[j];
printf("%d ",array2[j]);
}
printf("\n");
while( (sum1 != sum2)&&(endflag != 1) )
{
printf("sum1 = %d ,sum2 =%d \n",sum1,sum2);
if(sum1 < sum2)
{
kv_change(array1, &sum1, LENGTH1, array2, &sum2, LENGTH2, 1 );
}
else
{
kv_change(array2, &sum2, LENGTH2, array1, &sum1, LENGTH1, 0);
}
for(i=0;i<LENGTH1;i++)
{
printf("%d ",array1[i]);
}
printf("\n");
for(j=0;j<LENGTH2;j++)
{
printf("%d ",array2[j]);
}
printf("\n");
}
return 0;
}
- 交换两个数组使两个数组和的差最小
- 交换两个数组使两个数组和的差最小
- 交换两个数组使两个数组和的差最小
- 交换两个数组使两个数组和的差最小
- 交换两个数组使两个数组和的差最小
- 交换两个数组的元素,使两个数组和的差最小
- 通过交换两个数组的元素,使数组元素和之差最小
- 数组分割问题(另一种说法是交换两个数组元素使两个数组和的差最小)
- 华为面试题:通过交换元素,使两个数组的元素和之差最小
- 交换两个数组使两个数组和的差最小(转载)
- 给定两个数组,交换它们的元素,使得两数组元素之和的差绝对值最小
- 交换两数组中的元素使得这两个数组的差最小
- 交换两个长度均为n的无序数组的元素,使两数组元素的和之差的绝对值最小
- 交换两个数组值使两个数组之差最小
- 交换两个数组值使两个数组之差最小
- 交换两个数组值使两个数组之差最小
- 有两个数组a,b,大小都为n,数组元素的值任意,无序;要求:通过交换a,b中的元素,使数组a元素的和与数组b元素的和之间的差最小
- 有两个数组a,b,大小都为n,数组元素的值任意,无序;要求:通过交换a,b中的元素,使数组a元素的和与数组b元素的和之间的差最小
- 杂记_一点总结
- 每天学习一算法系列(17)(在一个字符串中找到第一个只出现一次的字符)
- 开源 HTTP加速器 Varnish
- PPT中的控件
- 进程 进程通信 死锁
- 交换两个数组的元素,使两个数组和的差最小
- js 获取 服务器系统时间
- PC 110301 || uva 10082 WERTYU //水题,但是PC格式错误,UVA AC
- USING INDUCTION TO DESIGN 使用归纳法设计算法 [9/14]
- s:checkboxlist的用法,以及取默认值,
- CRM小问题解决办法(1)
- CSS兼容IE6,IE7,FireFox之一
- 内核访问外设I/O资源方式
- tabHost研究二 ,android应用中,大部分的软件都会采用把按钮放在底部显示(tabHost)。利用三个Radiobutton嵌套在RadioGroup 。