Kadane's algorithm for printing the elements of the maximum subarray found?

时间:2017-08-05 12:17:27

标签: arrays algorithm

I modified the Kadane's algorithm to the following so that it works even in the case wherein I have all negative numbers in the array.

//Largest Sum Contiguous Subarray
#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <utility>
#include <algorithm>

using namespace std;

#define ll long long
#define pb push_back
#define mp make_pair
#define F(i,a,b) for(int i = (int)(a); i < (int)(b); i++)
#define RF(i,a,b) for(int i = (int)(a); i >= (int)(b); i--)
#define SIZE 100000

int main (void)
{
    vector<int> myvec;
    int arr[SIZE];
    int index[SIZE] = {0};
    int n;
    cin>>n;
    F(i,0,n)
    {
        cin>>arr[i];
    }
    int maxendinghere = arr[0];
    int maxsofar = arr[0];
    F(i,1,n)
    {
        if (arr[i] > (arr[i]+maxendinghere))
            myvec.pb(i);  // used for finding the elements of the subarray
        maxendinghere = max(arr[i],arr[i]+maxendinghere); 
        maxsofar = max(maxendinghere,maxsofar);
    }
    cout<<maxsofar<<"\n";
    auto it = myvec.begin(); // printing the subarray
    while (it != myvec.end())
    {
        cout<<*it<<"\t";
        it++;
    }
    cout<<"\n";
    return 0;

}

Now, I am trying to print the actual elements that form the subarray. One thing that I was able to think of was that the everytime (arr[i]+maxendinghere) will be greater than arr[i], a new element will be a part of the subarray and I push that in a vector and print the elements. But this doesn't give out the actual subarray correctly. What am I missing in this thought process? Thanks!

PS: I understand this is not the best coding style, but this was asked in an interview and I was trying to code it. I couldn't back then and hence this is what I was able to come up with.

Edit: Answer) I was able to code it up after the answer given by templatetypedef. The folllowing is the implementation.

//Largest Sum Contiguous Subarray
#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <utility>
#include <algorithm>

using namespace std;

#define ll long long
#define pb push_back
#define mp make_pair
#define F(i,a,b) for(int i = (int)(a); i < (int)(b); i++)
#define RF(i,a,b) for(int i = (int)(a); i >= (int)(b); i--)
#define SIZE 100000

int main (void)
{
    int currsum[SIZE],maxsumsofar[SIZE],sindex[SIZE],eindex[SIZE];
    int arr[SIZE];
    int start,end,n;
    cin>>n;
    F(i,0,n)
    {
        cin>>arr[i];
    }
    currsum[0] = arr[0];
    maxsumsofar[0] = arr[0];
    sindex[0] = 0;
    eindex[0] = 0;
    F(i,1,n)
    {
        if (arr[i] > (arr[i]+currsum[i-1])) // for starting index
            sindex[i] = i;
        else
            sindex[i] = sindex[i-1];

        currsum[i] = max(arr[i],arr[i]+currsum[i-1]);
        maxsumsofar[i] = max(currsum[i],maxsumsofar[i-1]);

        if (arr[i] > (arr[i]+currsum[i-1]))
            eindex[i] = i;
        else
        {
            if (maxsumsofar[i] == maxsumsofar[i-1])
                eindex[i] = eindex[i-1];
            else
                eindex[i] = i;
        }
    }
    cout<<maxsumsofar[n-1]<<"\n";
    F(i,0,n)
    {   
        if (maxsumsofar[i] == maxsumsofar[n-1])
        {
            start = sindex[i];
            end = eindex[i];
            break;
        }
    }
    cout<<"The array lies between indices "<<start<<" to "<<end<<"\n";
    return 0;
}

1 个答案:

答案 0 :(得分:1)

Kadane的算法通过维持子阵列的起始位置并反复查看数组中的下一个元素并决定

来工作。
  1. 通过附加该元素或
  2. 来扩展子阵列
  3. 丢弃子阵列并在该元素之后开始新的子阵列。
  4. 如果你明确地跟踪当前子阵列的起始点(最初它在数组的第一个元素之前,并且每当总数下降到零以下时重置),那么找到它不应该太难最佳子阵列。每次更新找到的最大子阵列时,您都可以

    1. 刚刚将一个新元素添加到现有的最大子数组中(所以只是追加到目前为止找到的最好的元素),或者
    2. 找到了一个新的子阵列,它位于与前一个最佳子阵列不同的位置,所以抛出旧的max并用这个新的替换它。
    3. 您可以通过跟踪目前为止的最大子阵列以及其起始位置来实现此目的。如果max子阵列与当前数组的位置相同,则为(1),否则为case(2)。