编程之美2.18学习笔记
2011-08-14 11:45 MichaelYin 阅读(549) 评论(0) 收藏 举报解题过程中没有使用书上提供的动态规划的算法,在这里把解题思路写一下。
题目是这样的,有个包含2n个元素的无序数组,现在用算法将这个数组进行分割,使得两个子数组的和最相近
我们首先来想像将数组分割后的情况,假设分割后的两个数组分别为A和B,A[0]和B[0]之间肯定是存在一个差值的,假设我们用A[0]-B[0],得到的值加上A[1]-B[1],这样最后得到的值的绝对值肯定是所有情况里面最小的,因为最后得到的绝对值其实就是两个数组的和的差值。
现在我们已经隐隐感觉到,其实两个元素之间的差值是我们可以拿来用的一个条件。我们只需要保证差值的绝对值为最小,这样得到的两个数组就是我们所求的结果了。然后还有一个问题,两个数组对应元素之间的差值是不一样的。比如A[0]-B[0]的差值是1,A[1] –B[1]的差值可能是99,我们需要一种策略来保证我们在计算这个差值的绝对值一定是最小。借鉴一下权重的思想,我们需要把本来差值绝对值最大的那一组A和B对应的元素放到前面去,然后依次排序,这样得到的相当于就是权重一个从大到小的顺序,我们遍历的时候就能够得到正确的结果,不至于前面出现了很多小的差值,然后因为后面出现了一个很大的差值,(比如99)使得得到的结果错误。
下面完整的将一遍解题思路,首先将原来的数组进行排序,排序是能够使得元素之间的差值之和最小(但是写这篇博客的时候我觉得这一步不是必须的,因为我需要的是差值信息,由于时间有限,就还是按照我以前的思路讲了)。排序完成之后我将元素按照排序的顺序放到两个数组subArray1和subArray2中去,这里subArray1的每个元素都会小于等于对应的subArray2元素。在遍历放到subArray1和subArray2的时候顺便将两者的差值信息专门用subSub数组放起来。
现在我们就有了三个数组,两个是元素,一个是元素对应的差值的信息,但是差值信息由权重的问题,考虑到我上面说的,我们需要将最大的差值放到前面去,这样在这里需要对subSub进行排序,需要注意的是,排序移动元素的时候,subArray1和subArray2的元素也需要进行相对应的移动。
到这里基本的东西都准备好了,然后就是一个for循环,对每个差值进行比较,原则就是一个,保证绝对值最小,如果需要将差值加法转换为减法运算,只需要调换subArray1和subArray2对应的元素就行了。这样遍历之后就能保证求出的差值的绝对值最小了。
下面贴出我试验的代码
public static void main(String[] args) {
// TODO Auto-generated method stub
// 初始排序没有写,为了快速解题就直接是写的已经排好了的数组
int[] testArray = new int[] { 1, 3, 5, 6, 7, 8, 9, 11, 17, 20 };
Test218(testArray);
}
public static void Test218(int[] array) {
// 数组用来存放结果
int[] subArray1 = new int[array.length / 2];
int[] subArray2 = new int[array.length / 2];
// 存放差值
int[] subSub = new int[array.length / 2];
for (int i = 0, j = 0; i < array.length; i = i + 2, j++) {
// 将两个数分别放到两个数组中去,同时计算两个数的差值,放到subSub数组中
subArray1[j] = array[i];
subArray2[j] = array[i + 1];
subSub[j] = array[i + 1] - array[i];
}
Sort(subArray1, subArray2, subSub);
int sum = subSub[0];
// 对subSub进行遍历
for (int i = 1; i < subSub.length; i++) {
// 求绝对值
if (Math.abs(sum - subSub[i]) < Math.abs(sum + subSub[i])) {
// 调换
swap(subArray1, subArray2, i, i);
sum = sum - subSub[i];
} else {
sum = sum + subSub[i];
}
}
for (int i : subArray1) {
System.out.print(i + " ");
}
System.out.println();
for (int i : subArray2) {
System.out.print(i + " ");
}
}
// 根据subSub数组中的差值进行快速排序,确保最大的差值放在最前面
public static void Sort(int[] subArray1, int[] subArray2, int[] subSub) {
// 先用冒泡,可以用快排优化
for (int i = 0; i < subSub.length - 1; i++)
for (int j = i + 1; j < subSub.length; j++) {
if (subSub[j] > subSub[i]) {
// 三个数组中的元素都需要进行调换
swap(subArray1, subArray1, i, j);
swap(subArray2, subArray2, i, j);
swap(subSub, subSub, i, j);
}
}
}
public static void swap(int[] array1, int[] array2, int i, int j) {
int temp = array1[i];
array1[i] = array2[j];
array2[j] = temp;
}
浙公网安备 33010602011771号