关于一个数组的算法问题

那天去面试,做到了一题笔试题。题目看上去很简单。具体如下:就是有一个数组,内容随机,长度不定,要求把他分成两个子数组,使得这两个子数组的和最接近(当然原题是差最小)。我给出的思路是这样的:①算出大数组和的一半A②将数组排序后取第一个值B③对数组做循环,从i=0开始,判断B是否小于等于A,如果是,则取i+1的数+B判断是否小于等于A,如果是则继续判断,直至i+1的数加上后超出A,此时子数组1即为0-i的值,剩下子数组2即为i+1以后的值。当初我也不知道对不对,总感觉思路不对,于是在答题的结尾还补了一句思路可能不对。后来结束后我去网上查了下,给出的方案大体一致,不同的是并没有对原数组进行排序。核心思想也是:在array中选取若干个元素,使得这些元素的和<=sum/2,且是最接近sum/2的元素集合。方法也有不同,网上给出的是

建一个数组:int[][]f=new int[length+1][sum/2+1]

状态方程:f[i][j]=Max(f[i-1][j-array[i]]+array[i],f[i-1][j])

解释:f[i][j]表示array中i个元素的和<=j,且是最接近j的元素集合。f[i-1][j-array[i]]表示array中i-1个元素的和最接近j-array[i],所以f[i][j]应该是[i-1][j-array[i]]+array[i]和f[i-1][j]中最大的那个。有点像0-1背包问题。

 1 public class DivideArrayTest {  
 2   
 3     /** 
 4      * @param args 
 5      */  
 6     public static void main(String[] args) {  
 7         // TODO Auto-generated method stub  
 8         int[] array = { 1, 0, 1, 7, 2, 4 };  
 9         System.out.println(getMaxDiff(array));  
10   
11     }  
12   
13     /* f[i][j]表示i个元素装容量为j的背包能装的最大容量 */  
14     public static int getMaxDiff(int[] array) {  
15         int sum = getSum(array);  
16         int length = array.length;  
17         int[][] f = new int[length + 1][sum / 2 + 1];  
18         for (int i = 0; i < length; i++) {  
19             for (int j = 1; j <= sum / 2; j++) {  
20                 f[i + 1][j] = f[i][j];  
21                 if (array[i] <= j && f[i][j - array[i]] + array[i] > f[i][j]) {  
22                     f[i + 1][j] = f[i][j - array[i]] + array[i];  
23                 }  
24             }  
25         }  
26         return sum - 2 * f[length][sum / 2];  
27     }  
28   
29     public static int getSum(int[] array) {  
30         int sum = 0;  
31         for (int i = 0; i < array.length; i++) {  
32             sum += array[i];  
33         }  
34         return sum;  
35     }  
36   
37 }  

说实话,不是很理解,我觉得按我的方式是否更加好一点呢?

原文地址:https://www.cnblogs.com/timePasser-leoli/p/8583704.html