寻找子阵列的最小绝对和

时间:2014-09-22 02:31:30

标签: algorithm sum dynamic-programming absolute-value kadanes-algorithm

有一个包含(正和负)整数的数组A。找到一个(连续的)子元素,其元素的绝对和是最小的,例如:

A = [2, -4, 6, -3, 9]
|(−4) + 6 + (−3)| = 1 <- minimal absolute sum

我已经开始实施一个强制算法O(N^2)O(N^3),尽管它产生了正确的结果。但任务规定:

complexity:
- expected worst-case time complexity is O(N*log(N))
- expected worst-case space complexity is O(N)

经过一番搜索,我认为可能会修改Kadane的算法以适应这个问题,但我没有做到。

我的问题是 - 卡丹的算法是正确的方法吗?如果没有,你能指出我正确的方向(或命名一个可以帮助我的算法)?我不想要现成的代码,我只需要帮助找到正确的算法。

10 个答案:

答案 0 :(得分:16)

如果计算部分和  比如

2, 2 +(-4), 2 + (-4) + 6, 2 + (-4) + 6 + (-3)...

然后,任何连续子阵列的总和是两个部分和的差值。因此,为了找到绝对值最小的连续子阵列,我建议您对部分和进行排序,然后找到最接近的两个值,并使用原始序列中这两个部分和的位置来查找开始和结束具有最小绝对值的子阵列。

这里的代价很高,所以我认为这会及时运行O(n * log(n))

答案 1 :(得分:6)

这是Saksow算法的C ++实现。

int solution(vector<int> &A) {
    vector<int> P;
    int min = 20000 ;
    int dif = 0 ;
    P.resize(A.size()+1);
    P[0] = 0;
    for(int i = 1 ; i < P.size(); i ++)
    {
        P[i] = P[i-1]+A[i-1];

    }
    sort(P.begin(),P.end());
    for(int i = 1 ; i < P.size(); i++)
    {
         dif = P[i]-P[i-1];
         if(dif<min)
         {
             min = dif;
         }
    }
    return min;
}

答案 2 :(得分:5)

我正在对Codility进行这项测试,我发现mcdowella的回答非常有帮助,但还不够,我不得不说:所以这是2015年的回答!

我们需要构建数组A的前缀和(这里称为P),如:P [0] = 0,P [1] = P [0] + A [0],P [2] = P [1 ] + A [1],...,P [N] = P [N-1] + A [N-1]

&#34; min abs sum&#34; A将是P中2个元素之间的最小绝对差值。所以我们只需要.sort() P并循环遍历每次2个连续元素。这样我们就有O(N + N log(N)+ N)等于O(N log(N))。

那就是它!

答案 3 :(得分:3)

答案是肯定的,Kadane的算法绝对是解决问题的方法。

http://en.wikipedia.org/wiki/Maximum_subarray_problem

资料来源 - 我与一位博士生密切合作,他的整个博士论文致力于解决最大的子阵列问题。

答案 4 :(得分:0)

def min_abs_subarray(a):
    s = [a[0]]
    for e in a[1:]:
        s.append(s[-1] + e)
    s = sorted(s)
    min = abs(s[0])
    t = s[0]
    for x in s[1:]:
        cur = abs(x)
        min = cur if cur < min else min
        cur = abs(t-x)
        min = cur if cur < min else min
        t = x
    return min

答案 5 :(得分:0)

短小甜蜜,像魅力一样工作。 JavaScript / NodeJs解决方案

 function solution(A, i=0, sum =0 ) {
    //Edge case if Array is empty
    if(A.length == 0) return 0;
    // Base case. For last Array element , add and substart from sum
    //  and find min of their absolute value
    if(A.length -1 === i){
        return Math.min( Math.abs(sum + A[i]), Math.abs(sum - A[i])) ;
    }
    // Absolute value by adding the elem with the sum.
    // And recusrively move to next elem
    let plus = Math.abs(solution(A, i+1, sum+A[i]));
    // Absolute value by substracting the elem from the sum
    let minus = Math.abs(solution(A, i+1, sum-A[i]));
    return Math.min(plus, minus);
}

console.log(solution([-100, 3, 2, 4]))

答案 6 :(得分:0)

这是python中的迭代解决方案。它100%正确。 http://schrodinger.github.io/fixed-data-table-2/example-object-data.html

 def solution(A):
    memo = []
    if not len(A):
        return 0

    for ind, val in enumerate(A):
        if ind == 0:
            memo.append([val, -1*val])
        else:
            newElem = []
            for i in memo[ind - 1]:
                newElem.append(i+val)
                newElem.append(i-val)
            memo.append(newElem)
    return min(abs(n) for n in memo.pop())

答案 7 :(得分:-1)

这是基于Kadane算法的C解决方案。 希望它有用。

#include <stdio.h>
int min(int a, int b)
{
  return (a >= b)? b: a;
}

int min_slice(int A[], int N) {
if (N==0 || N>1000000) 
return 0;

int minTillHere = A[0];
int minSoFar = A[0];
int i;
for(i = 1; i < N; i++){
    minTillHere = min(A[i], minTillHere + A[i]);
    minSoFar = min(minSoFar, minTillHere);
    }
return minSoFar;
}


int main(){
int A[]={3, 2, -6, 4, 0}, N = 5;
//int A[]={3, 2, 6, 4, 0}, N = 5;
//int A[]={-4, -8, -3, -2, -4, -10}, N = 6;
printf("Minimum slice = %d \n", min_slice(A,N));
return 0;
}

答案 8 :(得分:-1)

public static int solution(int[] A) {
    int minTillHere = A[0];
    int absMinTillHere = A[0];
    int minSoFar = A[0];
    int i;
    for(i = 1; i < A.length; i++){
        absMinTillHere = Math.min(Math.abs(A[i]),Math.abs(minTillHere + A[i]));
        minTillHere = Math.min(A[i], minTillHere + A[i]);
        minSoFar = Math.min(Math.abs(minSoFar), absMinTillHere);
        }
    return minSoFar;
}

答案 9 :(得分:-1)

您可以运行 <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> <div id="myModal" class="modal hide fade"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button> <div class="pull-right"> <div class="overlay"> <a class="btn" rel="popover" href="#" name="link-menu" data-content="Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. " data-original-title="A Title" data-placement="bottom"> popover menu </a> </div> </div> <h3>What is Lorem Ipsum?</h3> </div> <div class="modal-body"> <p> Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. </p> </div> <div class="modal-footer"> <a href="#" class="btn">Close</a> <a href="#" class="btn btn-primary">Save changes</a> </div> </div> <a href="#myModal" role="button" class="btn" data-toggle="modal">Launch demo modal</a> 两次(或一次性完成)查找最小和最大总和,其中查找最小值的工作方式与最大值相同反转符号,然后通过比较它们的绝对值来计算新的最大值。

来源 - 有人(不记得是谁)在这个网站上发表评论。