连续子段绝对值最小问题
2012-03-26 22:54
651 查看
【座右铭】1. 想要成为行家,就必须尝试解决大量的问题;
2. 解决大量问题并不代表能解决所有问题,而是表示解决下一个问题的几率变大了
1. 现有一个数组,里面包含了正数和负数,取其中若干个连续的数,要求这些数的和的绝对值最小【问题来源于论坛】
第一部分:思路
1. 对数组A[1...N],做和运算S[1...N],其中S[1] = A[1]; S[2] = A[1]+A[2];...;S
=A[1]+A[2]+A[3]+...+A
2. 对S[1...N]从小到大排序
3. 连续子段绝对值最小:Min{ |S[i]|,S[i+1]-S[i]} 1<=i<=N
第二部分:Java代码,不考虑异常情况
//待修正,在获取连续子段在原数组中的开始索引和结束索引有bug。
//代码中存在错误的判断条件:S[i+1]对应的索引大于S[i]对应的索引
//问题提出日期:4.18
第三部分:测试用例
数组{2,2,2,2}:返回{2,0,0}
数组{2,-2,1,3,4,-4}:返回{0,0,1}
数组{-2,1,2,-1,4}:返回{0,0,3}
数组{-2,3,1,-3,4,6,-7,2,8}:返回{0,3,6}
数组{-2,-6,-7,-3}:返回{2,0,0}
2. 解决大量问题并不代表能解决所有问题,而是表示解决下一个问题的几率变大了
1. 现有一个数组,里面包含了正数和负数,取其中若干个连续的数,要求这些数的和的绝对值最小【问题来源于论坛】
第一部分:思路
1. 对数组A[1...N],做和运算S[1...N],其中S[1] = A[1]; S[2] = A[1]+A[2];...;S
=A[1]+A[2]+A[3]+...+A
2. 对S[1...N]从小到大排序
3. 连续子段绝对值最小:Min{ |S[i]|,S[i+1]-S[i]} 1<=i<=N
第二部分:Java代码,不考虑异常情况
//待修正,在获取连续子段在原数组中的开始索引和结束索引有bug。
//代码中存在错误的判断条件:S[i+1]对应的索引大于S[i]对应的索引
//问题提出日期:4.18
/** * 现有一个数组,里面包含了正数和负数,取其中若干个连续的数,要求这些数的和的绝对值最小 * @param source * 数组 * @param len * 数组长度 * @return * 一个三元组,分别是最小值,连续子段在原数组中的开始索引,结束索引 */ public static int[] minAbs(int[] source, int len) { //保存最小值,连续子段在原数组中的开始索引,结束索引 int[] result = new int[3]; //和数组 int[] sum = new int[len]; sum[0] = source[0]; for(int i=1;i<len;i++) { source[i] += source[i-1]; sum[i] = source[i]; } //排序 quicksort(sum, 0, len-1); boolean isFromZero = false; result[0] = sum[0]>0?sum[0]:-1*sum[0]; isFromZero = true; result[1] = 0; result[2] = sum[0]; for(int j=1;j<len;j++) { int cur = sum[j]>0?sum[j]:-1*sum[j]; if(cur<result[0]) { result[0] = cur; isFromZero = true; result[1] = 0; result[2] = sum[j]; } cur = sum[j] - sum[j-1]; if(cur<result[0]) { result[0] = cur; isFromZero = false; result[1] = sum[j-1]; result[2] = sum[j]; } } //还原数组 int k = len - 1; for(;k>=0;k--) { if(source[k]==result[2]) { result[2] = k; break; } } if(!isFromZero) { for(k=0;k<result[2];k++) { if(source[k]==result[1]) { result[1] = k+1; break; } } } for(k=len-1;k>0;k--) { source[k] -= source[k-1]; } return result; } /** * 快速排序 */ static void quicksort(int[] source, int left, int right) { if(left<right) { int mid = partition(source, left, right); quicksort(source, left, mid-1); quicksort(source, mid+1, right); } } static int partition(int[] source, int left, int right) { int start = left, end = right; int tmp = 0; left++; while(left<=right) { while(left<=end&&source[left]<=source[start]) { left++; } while(source[right]>source[start]) { right--; } if(left<right) { tmp = source[left]; source[left] = source[right]; source[right] = tmp; } } tmp = source[start]; source[start] = source[right]; source[right] = tmp; return right; }
第三部分:测试用例
数组{2,2,2,2}:返回{2,0,0}
数组{2,-2,1,3,4,-4}:返回{0,0,1}
数组{-2,1,2,-1,4}:返回{0,0,3}
数组{-2,3,1,-3,4,6,-7,2,8}:返回{0,3,6}
数组{-2,-6,-7,-3}:返回{2,0,0}
相关文章推荐
- 终于搞清楚了C#二进制的一些关键操作了,解决了微软面试题,求数组中两两之差绝对值最小的值O(N)最少内存限制的问题!
- 【转】关于int范围中负数最小值的绝对值比整数最大值大初学C,问题源自:为什么C中的int类型(16位)的下溢下限为-32768而上溢上限却是32767。 首先说吧,32767很容易理解,32767
- 证明两个集合的划分最小绝对值差问题
- 【转】关于int范围中负数最小值的绝对值比整数最大值大初学C,问题源自:为什么C中的int类型(16位)的下溢下限为-32768而上溢上限却是32767。 首先说吧,32767很容易理解,32767=
- 关于int范围中负数最小值的绝对值比整数最大值大初学C,问题源自:为什么C中的int类型(16位)的下溢下限为-32768而上溢上限却是32767。 首先说吧,32767很容易理解,32767=
- A题之绝对值最小问题
- 证明两个集合的划分最小绝对值差问题
- 杭电1233——还是通畅工程~简单最小生成树问题
- 【网络流24题】魔术球问题 二分答案+最小路径覆盖
- 数组分段和最大值最小问题
- 交换两个长度均为n的无序数组的元素,使两数组元素的和之差的绝对值最小
- [连通度问题,最小割]
- 算法:求比指定数大且最小的“不重复数”问题的高效实现
- 【转】[面试题] 求数组两两之差绝对值最小的值
- poj 2125 最小割解决 "最小点权覆盖问题" +输出解(割边集)
- 求一个已排序的数组中绝对值最小的元素
- 初级硬币最大最小问题递推法
- CSS网页布局中的最小高度问题的解决方法
- 最小m段和问题
- 有向图最小环问题