和差值最小子数组划分
2012-04-01 10:53
169 查看
有一个数列,要采取怎样的划分方法把它分成2个数列,使得2个数列的各自之和的差最小。
比如一个数列(5,8,13,27,14),通过分成(5,13,14)和(8,27),这样2个数列各自的和再作差就等于35-32=3,这样差值最小。
暂时有两种想法可以做,现在只给出第一种的代码(C#)
1. 动态规划
(1)就是根据输入数组的长度(N),把这个问题看成一个N歩动态规划的问题。
(2)对于动态规划,需要有状态变量记录当前的状态(这里有当前歩i,前面的选择情况,当前的差值);
(3)对于每一步的选择有两种,比如第i歩时,选择将第i个数放入数组1或者数组2。
最后的实现就是递归状态变量得到。
2. 枚举所有可能的差值
(1) 对于有限的数组,算出所有数分成两组可能的绝对值是可能的。
(2) 通过递归的形式,将长度大于2的数组,划分为两个较小的数组,然后分别计算它们可能得到的差值。然后再定义,两个子数组差值合并的计算方法和数组长度为2时的计算方法即可。
(3) 对于两个子数组差值合并的计算,把差值按照一定顺序排列,建立每个差值和整个数组分组的对应关系,所以不用记录每个差值对应的分组。
最后的实现就是递归数组得到。
比如一个数列(5,8,13,27,14),通过分成(5,13,14)和(8,27),这样2个数列各自的和再作差就等于35-32=3,这样差值最小。
暂时有两种想法可以做,现在只给出第一种的代码(C#)
1. 动态规划
(1)就是根据输入数组的长度(N),把这个问题看成一个N歩动态规划的问题。
(2)对于动态规划,需要有状态变量记录当前的状态(这里有当前歩i,前面的选择情况,当前的差值);
(3)对于每一步的选择有两种,比如第i歩时,选择将第i个数放入数组1或者数组2。
最后的实现就是递归状态变量得到。
2. 枚举所有可能的差值
(1) 对于有限的数组,算出所有数分成两组可能的绝对值是可能的。
(2) 通过递归的形式,将长度大于2的数组,划分为两个较小的数组,然后分别计算它们可能得到的差值。然后再定义,两个子数组差值合并的计算方法和数组长度为2时的计算方法即可。
(3) 对于两个子数组差值合并的计算,把差值按照一定顺序排列,建立每个差值和整个数组分组的对应关系,所以不用记录每个差值对应的分组。
最后的实现就是递归数组得到。
struct choiceSet { public int choice; public int value; public int position; } public static int minVal = 0, choiceFinal = 0; static void Main(string[] args) { List<int> originalList = new List<int>(); string input = Console.ReadLine(); char splitcomma = ','; string[] temp = input.Split(splitcomma); foreach (string s in temp) { originalList.Add(getNum(s)); minVal += Convert.ToInt32(getNum(s)); } choiceSet cs0; cs0.choice = 1; cs0.value = 0; cs0.position = 0; stepOne(originalList, cs0); writeResult(originalList, choiceFinal); Console.ReadKey(); } static void writeResult(List<int> li, int choice) { Console.WriteLine("[Value,Group]"); for (int i = 0; i < li.Count; i++) { Console.WriteLine("[{0},{1}]", li[li.Count-1-i], choice % 2 + 1); choice=(choice-choice%2)/2; } Console.WriteLine("The difference is {0}.",minVal); } static void stepOne(List<int> li, choiceSet cs) { if (cs.position == 0) { choiceSet cs1; cs1.choice = cs.choice * 2 + 0; cs1.value = cs.value + li[cs.position]; cs1.position = cs.position + 1; stepOne(li, cs1); } else if (cs.position < li.Count - 1) { choiceSet cs1, cs2; cs1.choice = cs.choice * 2 + 0; cs1.value = cs.value + li[cs.position]; cs1.position = cs.position + 1; cs2.choice = cs.choice * 2 + 1; cs2.value = cs.value - li[cs.position]; cs2.position = cs.position + 1; stepOne(li, cs1); stepOne(li, cs2); } else { if (Math.Abs(cs.value + li[cs.position]) <= Math.Abs(cs.value + li[cs.position])) { int fValue = cs.value + li[cs.position]; if (Math.Abs(fValue) < Math.Abs(minVal)) { minVal = fValue; choiceFinal = cs.choice * 2 + 0; } } else { int fValue = cs.value - li[cs.position]; if (Math.Abs(fValue) < Math.Abs(minVal)) { minVal = fValue; choiceFinal = cs.choice * 2 + 1; } } } } static int getNum(string s) { char[] temp = s.ToCharArray(); int sign = 1; int sum = 0; foreach (char c in temp) { if (c == '-') sign = -1; else sum = sum * 10 + ((int)c - 48); } return sum * sign; }
相关文章推荐
- 划分数组,求最小差值
- 面试题:数组划分成两个子数组,和的差值的绝对值最小
- 将一个数组划分为和差值最小的子数组
- 将一个数组划分为和差值最小的子数组
- 数组划分 求划分结果的差值
- C/C++如何把一个特定分隔符分割的字符串划分为一个字符串数组,strtok(char *,char*)分割函数
- LintCode:数组划分
- LeetCode 209. Minimum Size Subarray Sum(最小子数组之和)
- 数组的定义与内存的划分
- 求两个有序数组中,各个元素的c差值最小
- 03、数组&内存划分
- 无序数组排序后的最大相邻差值
- 桶---求无序数组排序后,最大的相邻差值
- 一个数组~~左划分最大值减右划分最大值的绝对值
- <LeetCode> 题31:数组划分
- 无序数组排序后的最大相邻差值
- 数组划分--lintcode
- 重载(overload)+数组 内存的划分
- php 算法之切割数组,不用array_chunk(),算法之二,取数组的差值,不用array_diff()
- php-Arrays 函数-array_diff_key-使用键名比较计算数组的差值