【问题标题】:Efficiently calculate cumulative sum of a multidimensional array?有效计算多维数组的累积和?
【发布时间】:2020-06-26 15:59:32
【问题描述】:

如果我有一个一维数组 arr[x]

cumulative_arr[x]=cumulative_arr[x-1]+arr[x]

对于二维数组 arr[x][y]

cumulative_arr[x][y]=cumulative_arr[x-1][y]+cumulative_arr[x][y-1]-cumulative_arr[x-1][y-1]+arr[x][y]

如何将这种方法扩展到更大维度的数组?

4D 数组的累积和为:-

cumulative_sum[w][x][y][z] = sum of arr[i][j][k][l] for all i<=w,j<=x,k<=y and l<=z.

我想找到一个 N 维数组的方法。

【问题讨论】:

  • 代码是Python还是C++
  • 任何实现/抽象都可以。我标记了两者以确保我不会遇到其他问题。
  • 那么问题是关于在大型二维数组中找到任何矩形的总和?
  • 不,这是关于找到任何多维数组的累积和。我将编辑帖子以包含更多详细信息
  • 那么,你想求cumsum_arr[i, j, k, ...]cumsum_arr[i - 1, j, k, ...]cumsum_arr[i, j - 1, k, ...]cumsum_arr[i, j, k - 1, ...]等之间的N维递推关系对吗?

标签: c++ python-3.x algorithm data-structures


【解决方案1】:

既然你标记为 C++,那么我们开始吧……

一维:

static const unsigned int ARRAY_CAPACITY = 64u;
int sum = 0;
sum = std::accumulate(&array[0], &array[ARRAY_CAPACITY], 0);

二维:

static const unsigned int MAXIMUM_ROWS = 32u;
static const unsigned int MAXIMUM_COLUMNS = 16u;
int sum = 0;
sum = std::accumulate(&array[0][0], &array[MAXIMUM_ROWS][MAXIMUM_COLUMNS], 0);

三维(说明经典的for 循环):

int sum = 0;
for (int x = 0; x < CAPACITY_DIMENSION_3; ++x)
{
    for (int y = 0; y < CAPACITY_DIMENSION_2; ++y)
    {
        for (int z = 0; z < CAPACITY_DIMENSION_1; ++z)
        {
            sum += array[x][y][z];
        }
    }
}

如果数组槽对于所有维度都是连续的,则可以将数组转换为一维,并求和为一维数组。

【讨论】:

  • 计算整个数组的总和。我想找到一个数组位置的累积和。一个例子是:对于所有 i
  • 您是在询问给定位置的数组中的值吗? Sum 通常意味着添加多个值。
  • 是的,实际上我的意思是数组每个位置的累积和。我在编辑中提供了我想要的临时定义。
  • 您可以将std::accumulate 替换为std::partial_sum (部分和是正确的术语,顺便说一句),并统一处理两个矩阵。我想知道是否可以为这些类型定义某种优雅的std::begin()
【解决方案2】:

您可以创建一个递归函数,如下所示:

function dimensionalSum(arr: any[]){
    if(typeof arr[0] == 'number'){
        return arr.reduce((acc, num) => acc + num, 0);
    }
    return arr.reduce((acc, dim) => acc + dimensionalSum(dim), 0);
}

注意:示例是用 typescript 编写的,它只是一个概念证明。

这样,你有多少维度都没有关系。

【讨论】:

    【解决方案3】:

    如果您只需要一种在任意 N 维数组的所有维度上计算累积和数组的方法,那么在 Python 中,您可以利用 NumPy 的cumsum() 的强大功能:

    import numpy as np
    
    
    def cumsum_all(arr):
        result = arr
        for i in range(arr.ndim):
            result = np.cumsum(result, i)
        return result
    

    测试这个会得到:

    arr = np.arange((2 * 3)).reshape((2, 3))
    
    print(arr)
    # [[0 1 2]
    #  [3 4 5]]
    
    print(cumsum_all(arr))
    # [[ 0  1  3]
    #  [ 3  8 15]]
    
    arr = np.arange((2 * 3 * 4)).reshape((2, 3, 4))
    
    print(arr)
    # [[[ 0  1  2  3]
    #   [ 4  5  6  7]
    #   [ 8  9 10 11]]
    #  [[12 13 14 15]
    #   [16 17 18 19]
    #   [20 21 22 23]]]
    
    print(cumsum_all(arr))
    # [[[  0   1   3   6]
    #   [  4  10  18  28]
    #   [ 12  27  45  66]]
    #  [[ 12  26  42  60]
    #   [ 32  68 108 152]
    #   [ 60 126 198 276]]]
    

    【讨论】:

      猜你喜欢
      • 2021-08-01
      • 2019-09-20
      • 2016-07-11
      • 2015-11-20
      • 1970-01-01
      • 2013-05-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多