每天学习一算法系列(29)(有两个序列a,b,大小都为n,序列元素的值任意整数,无序;要求:通过交换a,b 中的元素,使[序列a 元素的和]与[序列b 元素的和]之间的差最小)
2011-08-19 12:09
573 查看
题目:
有两个序列a,b,大小都为n,序列元素的值任意整数,无序;要求:通过交换a,b 中的元素,使[序列a 元素的和]与[序列b 元素的和]之间的差最小。
例如:
var a = [100,99,98,1,2, 3];
var b = [1, 2, 3, 4,5,40];
最后的结果为:
var a = [1,99,98,1,2,2];
var b = [100, 3,3,4,5,40];
思路一:
首先先计算a,b中元素和之间的差绝对值ABDis,然后逐一的把a中的元素和b中的任一元素作比较,如果它们交换后的差值绝对值ABTempDis小于原来的值ABDis,那么就把a,b交换,并重新计算a和b的绝对值,这种动作反复的进行,直到a中任一的元素都不能和b中的任一元素交换为止。(其实是穷举法)
代码如下:
思路二:
当前数组a和数组b的和之差为A = sum(a) - sum(b),a的第i个元素和b的第j个元素交换后,a和b的和之差为
A' = sum(a) - a[i] + b[j] - (sum(b) - b[j] + a[i])
= sum(a) - sum(b) - 2 (a[i] - b[j])
= A - 2 (a[i] - b[j])
设x = a[i] - b[j],那么
A' = |A - 2x|,当然A' 越小也好,所以当x 在 (0,A)之间时,做这样的交换才能使得交换后的a和b的和之差变小,x越接近A/2效果越好,如果找不到在(0,A)之间的x,则当前的a和b就是答案。
所以算法大概如下:在a和b中寻找使得x在(0,A)之间并且最接近A/2的i和j,交换相应的i和j元素,重新计算A后,重复前面的步骤直至找不到(0,A)之间的x为止。
代码和思路给出的代码差不多,这里就不给出代码了。
有两个序列a,b,大小都为n,序列元素的值任意整数,无序;要求:通过交换a,b 中的元素,使[序列a 元素的和]与[序列b 元素的和]之间的差最小。
例如:
var a = [100,99,98,1,2, 3];
var b = [1, 2, 3, 4,5,40];
最后的结果为:
var a = [1,99,98,1,2,2];
var b = [100, 3,3,4,5,40];
思路一:
首先先计算a,b中元素和之间的差绝对值ABDis,然后逐一的把a中的元素和b中的任一元素作比较,如果它们交换后的差值绝对值ABTempDis小于原来的值ABDis,那么就把a,b交换,并重新计算a和b的绝对值,这种动作反复的进行,直到a中任一的元素都不能和b中的任一元素交换为止。(其实是穷举法)
代码如下:
/*------------------------------- Copyright by yuucyf. 2011.08.19 --------------------------------*/ #include "stdafx.h" #include <iostream> #include <assert.h> using namespace std; __int64 MakeSmallly(int *pA, int i32ALen, int *pB, int i32BLen) { assert(pA); assert(pB); assert(i32ALen > 0); assert(i32BLen > 0); int i32I = 0, i32J = 0, i32Temp = 0; __int64 i64ASum = 0, i64BSum = 0; __int64 i64ABDis = 0, i64TempDis = 0; for (i32I = 0; i32I < i32ALen; i32I++) i64ASum += pA[i32I]; for (i32I = 0; i32I < i32BLen; i32I++) i64BSum += pB[i32I]; i64ABDis = _abs64(i64ASum - i64BSum); bool bSwap = false; for (i32I = 0; i32I < i32ALen; i32I++) { while (true) { for (i32J = 0; i32J < i32BLen; i32J++) { i64TempDis = _abs64((i64ASum - pA[i32I] + pB[i32J]) - (i64BSum - pB[i32J] + pA[i32I])); if (i64TempDis < i64ABDis) { i64ASum += (pB[i32J] - pA[i32I]); i64BSum += (pA[i32I] - pB[i32J]); i64ABDis = i64TempDis; i32Temp = pA[i32I]; pA[i32I] = pB[i32J]; pB[i32J] = i32Temp; bSwap = true; break; } } if (i32J >= i32BLen) break; } //如果有交换,且i32ALen的值为最后一个元素, //那么我们必须重新再来一遍,直到没有元素交换为止. if ((i32I == i32ALen - 1) && bSwap) { bSwap = false; i32I = -1; } } return i64ABDis; } int _tmain(int argc, _TCHAR* argv[]) { int aryA[] = {100, 99, 98, 1, 2, 3}; int aryB[] = {1, 2, 3, 4, 5, 40}; __int64 i64Dis = MakeSmallly(aryA, sizeof(aryA)/sizeof(aryA[0]), aryB, sizeof(aryB)/sizeof(aryB[0])); cout << "A,B系列元素的最小差为:" << i64Dis << ",最后的结果为,A系列元素为"; for (int i32I = 0; i32I < sizeof(aryA)/sizeof(aryA[0]); i32I++) cout << aryA[i32I] << " "; cout << ",B系列元素为"; for (int i32I = 0; i32I < sizeof(aryB)/sizeof(aryB[0]); i32I++) cout << aryB[i32I] << " "; cout << endl; return 0; }
思路二:
当前数组a和数组b的和之差为A = sum(a) - sum(b),a的第i个元素和b的第j个元素交换后,a和b的和之差为
A' = sum(a) - a[i] + b[j] - (sum(b) - b[j] + a[i])
= sum(a) - sum(b) - 2 (a[i] - b[j])
= A - 2 (a[i] - b[j])
设x = a[i] - b[j],那么
A' = |A - 2x|,当然A' 越小也好,所以当x 在 (0,A)之间时,做这样的交换才能使得交换后的a和b的和之差变小,x越接近A/2效果越好,如果找不到在(0,A)之间的x,则当前的a和b就是答案。
所以算法大概如下:在a和b中寻找使得x在(0,A)之间并且最接近A/2的i和j,交换相应的i和j元素,重新计算A后,重复前面的步骤直至找不到(0,A)之间的x为止。
代码和思路给出的代码差不多,这里就不给出代码了。
相关文章推荐
- 有两个序列a,b,大小都为n,序列元素的值任意整数,无序; 要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小。
- [微软]有两个序列a,b,大小都为n,序列元素的值任意整数,无序; 要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小
- [微软]有两个序列a,b,大小都为n,序列元素的值任意整数,无序; 要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小
- 有两个序列a,b,大小都为n,序列元素的值任意整数,无序;要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小。
- 《数组-规划》 有两个序列a,b,大小都为n,序列元素的值任意整数,无序;要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小
- 有两个序列a,b,大小都为n,序列元素的值任意整数,无序;要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小。
- 写正确函数需要注意的地方:两个序列a,b,大小都为n,序列元素的值为任意整数,无序;要求通过交换a,b中的元素,使序列a元素的和与序列b元素的和之间的差最小
- 有两个序列a,b,大小都为n,序列元素的值任意整数,无序;要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小。
- 有两个序列a,b,大小都为 n,序列元素的值任意整数,无序 通过交换a,b中的元素,使序列 a的和与序列b的和之间的差最小
- 有两个序列a,b,大小都有n,序列元素的值任意整数,无序; 要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b无素的和]之间的差最大。
- 华为面试题(8分钟写出代码) 有两个数组a,b,大小都为n,数组元素的值任意,无序; 要求:通过交换a,b中的元素,使数组a元素的和与数组b元素的和之间的差最小
- 有两个数组a,b,大小都为n,数组元素的值任意,无序;要求:通过交换a,b中的元素,使数组a元素的和与数组b元素的和之间的差最小
- 有两个序列a,b,大小都为n,序列元素的值任意整数,无序;要求:通过交换a,b中的元素,使[序列a元素的和
- 华为面试题 题目:有两个数组a,b,大小都为n,数组元素的值任意,无序; 要求:通过交换a,b中的元素,使数组a元素的和与数组b元素的和之间的差最小
- 【华为】题目:有两个数组a,b,大小都为n,数组元素的值任意,无序; 要求: 通过交换a,b中的元素,使数组a元素的和与数组b元素的和之间的差最小。
- 有两个数组a,b,大小都为n,数组元素的值任意,无序;要求:通过交换a,b中的元素,使数组a元素的和与数组b元素的和之间的差最小
- 华为面试题(8分钟写出代码) 有两个数组a,b,大小都为n,数组元素的值任意,无序; 要求:通过交换a,b中的元素,使数组a元素的和与数组b元素的和之间的差最小
- 有两个数组a,b,大小都为n,数组元素的值任意,无序; 要求:通过交换a,b中的元素,使数组a元素的和与数组b元素的和之间的差最小。
- 有两个序列a,b,要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小。
- 【编程题目】有两个序列 a,b,大小都为 n,序列元素的值任意整数,无序;(需要回头仔细研究)