【问题标题】:Find a subarray of m*m (2<=m<n) having largest sum; out of an n*n int array(having +ve, -ve, 0s)找到一个具有最大和的 m*m (2<=m<n) 子数组;在 n*n int 数组中(有 +ve, -ve, 0s)
【发布时间】:2014-09-04 07:19:07
【问题描述】:

我已经为上述问题编写了一个解决方案,但有人可以建议一种优化的方法。 我遍历了 count(2 到 n) 的数组,其中 count 正在查找大小为 count*count 的子数组。

int n = 5;      //Size of array, you may take a dynamic array as well
int a[5][5] = {{1,2,3,4,5},{2,4,7,-2,1},{4,3,9,9,1},{5,2,6,8,0},{5,4,3,2,1}};
int max = 0;
int **tempStore, size;

for(int count = 2; count < n; count++)
{
    for(int i = 0; i <= (n-count); i++)
    {
        for(int j = 0; j <= (n-count); j++)
        {
            int **temp = new int*[count]; 
            for(int i = 0; i < count; ++i) {
                temp[i] = new int[count];
            }

            for(int k = 0; k < count; k++)
            {
                for(int l = 0; l <count; l++)
                {
                    temp[k][l] = a[i+k][j+l];
                }
            }
            //printing fetched array
            int sum = 0;
            for(int k = 0; k < count; k++)
            {
                for(int l = 0; l <count; l++)
                {
                    sum += temp[k][l];
                    cout<<temp[k][l]<<" ";
                }cout<<endl;
            }cout<<"Sum = "<<sum<<endl;
            if(sum > max)
            {
                max = sum;
                size = count;
                tempStore = new int*[count]; 
                for(int i = 0; i < count; ++i) {
                    tempStore[i] = new int[count];
                }
                //Locking the max sum array
                for(int k = 0; k < count; k++)
                {
                    for(int l = 0; l <count; l++)
                    {
                        tempStore[k][l] = temp[k][l];
                    }
                }
            }
            //printing finished
            cout<<"------------------\n";
            //Clear temp memory
            for(int i = 0; i < size; ++i) {
                delete[] temp[i];
            }
            delete[] temp;
        }
    }
}

cout<<"Max sum is = "<<max<<endl;
for(int k = 0; k < size; k++)
{
    for(int l = 0; l <size; l++)
    {
        cout<<tempStore[k][l]<<" ";
    }cout<<endl;
}cout<<"-------------------------";

//Clear tempStore memory
for(int i = 0; i < size; ++i) {
    delete[] tempStore[i];
    }
delete[] tempStore;

例子:

1 2 3 4 5

2 4 7 -2 1

4 3 9 9 1

5 2 6 8 0

5 4 3 2 1

输出: 最大总和为 = 71

2 4 7 -2

4 3 9 9

5 2 6 8

5 4 3 2

【问题讨论】:

  • C 还是 C++?选择一个。
  • 我猜你的问题更适用于Code Review
  • (另外,请正确格式化。)
  • C 和 C++ 是不同的语言。实际上,更优雅的解决方案在每个方面看起来都非常不同。那么你需要哪一个?
  • 你的代码看起来很乱。请尝试清理它 - 代码中的语句 sn-ps cmets 在代码中吗?

标签: c++ c arrays


【解决方案1】:

这是一个最好使用动态编程 (DP) 或记忆化解决的问题。

假设 n 非常大,您会发现重新计算每个可能的矩阵组合的总和将花费太长时间,因此如果您可以重用之前的计算,那么一切都会变得更快。

这个想法是从较小的矩阵开始,计算较大的矩阵的总和,重复使用较小矩阵的预先计算值。

long long *sub_solutions = new long long[n*n*m];

#define at(r,c,i) sub_solutions[((i)*n + (r))*n + (c)]

// Winner:
unsigned int w_row = 0, w_col = 0, w_size = 0;

// Fill first layer:
for ( int row = 0; row < n; row++) {
    for (int col = 0; col < n; col++) {
        at(r, c, 0) = data[r][c];
        if (data[r][c] > data[w_row][w_col]) { 
            w_row = r;
            w_col = c;
        }           
    }
}

// Fill remaining layers.
for ( int size = 1; size < m; size++) {
    for ( int row = 0; row < n-size; row++) {
        for (int col = 0; col < n-size; col++) {
            long long sum = data[row+size][col+size];
            for (int i = 0; i < size; i++) {
                sum += data[row+size][col+i];
                sum += data[row+i][col+size];
            }
            sum += at(row, col, size-1); // Reuse previous solution.
            at(row, col, size) = sum;
            if (sum > at(w_row, w_col, w_size)) { // Could optimize this part if you only need the sum.
                w_row = row;
                w_col = col;
                w_size = size;
            }
        }
    }
}

// The largest sum is of the sub_matrix starting a w_row, w_col, and has dimensions w_size+1.
long long largest = at(w_row, w_col, w_size);

delete [] sub_solutions;

此算法具有复杂性:O(n*n*m*m) 或更准确地说:0.5*n*(n-1)*m*(m-1)。 (现在我还没有测试过,所以如果有任何错误,请告诉我。)

【讨论】:

    【解决方案2】:

    试试这个(使用幼稚的方法,会更容易理解):

    #include <iostream> 
    #include<vector>
    using namespace std; 
    int main( )
    { 
        int n = 5; //Size of array, you may take a dynamic array as well
        int a[5][5] = 
          {{2,1,8,9,0},{2,4,7,-2,1},{5,4,3,2,1},{3,4,9,9,2},{5,2,6,8,0}};
        int sum, partsum;
        int i, j, k, m;
        sum = -999999; // presume minimum part sum 
        for (i = 0; i < n; i++) {
            partsum = 0;
            m = sizeof(a[i])/sizeof(int);
            for (j = 0; j < m; j++) {
                partsum += a[i][j];
            }
            if (partsum > sum) {
                k = i;
                sum = partsum;
            }
        }
        // print subarray having largest sum
        m = sizeof(a[k])/sizeof(int); // m needs to be recomputed
        for (j = 0; j < m - 1; j++) {
            cout << a[k][j] << ", ";
        }
        cout << a[k][m - 1] <<"\nmax part sum = " << sum << endl;
        return 0;
    }
    

    【讨论】:

    • 感谢您的回复,但它没有给我想要的输出。我现在在问题中添加了一个示例。
    • 已编辑,有一个问题,m需要在最后循环之前重新计算
    【解决方案3】:

    使用累积和,您可以在恒定时间内计算部分和

    std::vector<std::vector<int>>
    compute_cumulative(const std::vector<std::vector<int>>& m)
    {
        std::vector<std::vector<int>> res(m.size() + 1, std::vector<int>(m.size() + 1));
    
        for (std::size_t i = 0; i != m.size(); ++i) {
            for (std::size_t j = 0; j != m.size(); ++j) {
                res[i + 1][j + 1] = m[i][j] - res[i][j]
                            + res[i + 1][j] + res[i][j + 1];
            }
        }
        return res;
    }
    
    int compute_partial_sum(const std::vector<std::vector<int>>& cumulative, std::size_t i, std::size_t j, std::size_t size)
    {
        return cumulative[i][j] + cumulative[i + size][j + size]
               - cumulative[i][j + size] - cumulative[i + size][j];
    
    }
    

    live example

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-28
      • 2016-07-02
      • 1970-01-01
      • 1970-01-01
      • 2021-06-09
      • 1970-01-01
      • 1970-01-01
      • 2014-10-22
      相关资源
      最近更新 更多