找到连续的第二个最小子数组

时间:2018-08-23 02:27:45

标签: c++

我正在编写一个函数,该函数除了数组的长度外,还包含指向动态分配的数组的指针。我试图找到它的连续子数组的第二个最小的和。

我一直在编写代码以计算数组中的第二个最小值,并且还编写了一段代码,用于计算所有连续子数组的和。我希望我能够将这两个部分“合并”在一起,以获得我想要的最终结果,但是我陷入了困境。我真的很感谢您的帮助。 谢谢。

#include <iostream>
using namespace std;

int secondSmallestSum(int *numbers,int length) 
{

//Below shows the sum of all contiguous sub arrays.
for(i = 0; i<= length; ++i)
{
    int sum = 0;
    for(int j = i; j <= length; ++j)
    {
        sum+=*(numbers+j);

    }
}


//Below calculates the second smallest element in an array

int smallest, secondsmallest;

if (*numbers < *(numbers+1))
{
    smallest = *numbers;
    secondsmallest = *(numbers+1) ;
}
else {
  smallest = *(numbers+1) ;
  secondsmallest = *(numbers) ;
}
for (i = 2; i < length; i++) {
    if (*(numbers+i)  < smallest) 
    {
    secondsmallest = smallest;
    smallest = *(numbers+i);
    }
    else if (*(numbers+i) < secondsmallest) 
    {
        secondsmallest = *(numbers+i);
    }
}   

}

3 个答案:

答案 0 :(得分:0)

您可以执行类似的操作(当然,您需要添加范围检查)。

#include <iostream>
#include <vector>
#include <algorithm>

int main(int argc, char** argv) {
  std::vector<int> v{3, 1, 4, 5, 6, 2};

  std::nth_element(v.begin(), v.begin() + 1, v.end());
  std::cout << "The second smallest element is " << v[1] << "\n";
}

注意:使用nth_element会更改向量中元素的顺序。

答案 1 :(得分:0)

如果我理解您有误,请纠正我,

通过查看“ 找到其连续子数组的第二个最小和 ”和您发布的代码,我假设您的逻辑是

  1. 计算所有可能的连续子数组的所有总和
  2. 在总和中找到第二个最小值

实际上,有一种众所周知的算法,即 Kadane算法 ,其用途相似(只有Kadane的算法找到的是最小的,而不是第二个最小的)。您可能需要在Google上查找更多内容。

回到您的问题,我相信以下代码可以满足您的需求。该代码是Kadane算法的一种变体。

#include <climits> // for INT_MAX
int findSecondMinOfContiguousSubarray(int arr[], int n)
{
    // to store the minimum value that is ending
    // up to the current index
    int min_ending_here = INT_MAX;

    int min = INT_MAX;              // absolute min
    int min_second = INT_MAX - 1;   // second min   <- this is what you want

                                    // traverse the array elements
    for (int i = 0; i<n/*it is <, not <=*/; i++)
    {
        // if min_ending_here > 0, then it could not possibly
        // contribute to the minimum sum further
        if (min_ending_here > 0)
            min_ending_here = arr[i];

        // else add the value arr[i] to min_ending_here    
        else
            min_ending_here += arr[i];

        // update min and min_second
        if (min_second > min_ending_here) {
            if (min > min_ending_here) {
                min_second = min;
                min = min_ending_here;
            }
            else {
                min_second = min_ending_here;
            }
        }
    }

    return min_second;
}

顺便说一句,我认为您的代码(//下面的代码显示了所有连续子数组的总和。)找不到所有连续子数组。

例如arr = {1,2,3},您的代码仅将{1,2,3},{2,3}和{3}视为连续的子数组,而实际上{1,2}还应该考虑。

答案 2 :(得分:0)

蛮力o(n^2)的复杂度(采用C ++而非C风格):

template<typename Container, typename Func>
void forEachSubrange(Container &container, Func &&f)
{
    for (auto subBegin = container.begin(); subBegin != container.end(); ++subBegin)
    {
        auto subEnd = subBegin;
        do {
            ++subEnd;
            f(subBegin, subEnd);
        } while (subEnd != container.end());
    }
}

int secondSmallestSubrangeSum(const std::vector<int> &a)
{
    int firstSum = 0; // empty sub range has zero sum
    int secondSum = 0;
    forEachSubrange(a, [&firstSum, &secondSum](auto b, auto e) {
        auto sum = std::accumulate(b, e, 0);
        if (sum < firstSum) {
            secondSum = firstSum;
            firstSum = sum;
        } else if (sum < secondSum) {
            secondSum = sum;
        }
    });
    return secondSum;
}

我确定可以实现o(n)

https://wandbox.org/permlink/9cplKBIpfZBPpZ27 或更健谈的https://wandbox.org/permlink/X21TdH6xtbMLpV19