繁体   English   中英

矩阵求和挑战

[英]Matrix Summation Challenge

下面的算法用于将“下矩阵”转换为“后矩阵”。 给定“后矩阵”,找到“前矩阵”。

矩阵

该算法针对每个 after(x,y) 运行以确定它们的值。 给定之后,找到之前的原始值

例子

之后 = [[2,5],[7,17]]

从之前计算之后的值

after[0][0] = before[0][0] = 2

after[0][1] = before[0][0] + before[0][1] = 2 + 3 = 5

after[1][0] = before[0][0] + before[1][0] = 2 + 5 = 7

after[1][1] = before[0][0] + before[0][1] + before[1][0] + before[1][1] = 2 + 3 + 5 + 7 =  17

完成 function 找到前矩阵有以下参数 after[n][m]:一个 nxm 整数数组

返回: int[n][m] 表示前矩阵的 nxm 整数数组

约束

再输入一个样本

输入1

到目前为止我尝试过的

n = gets.to_i
m = gets.to_i

arr = Array.new(n){Array.new(m,0)}
sum = 0
arr_last = 0
arr_first = 0
len = 0
a.each_with_index do |d, outer_index|
  len = d.length - 1
  d.each_with_index do |b, index|
    arr_sum = d[0..index].sum
    if index > 0
      arr[outer_index][index] = sum + arr_sum
    else
      arr[outer_index][index] = arr_first + b
    end
    arr_first += b if index == 0
    arr_last = arr_sum if index == len 
  end
  sum += arr_last
end

print arr

但是对于少数测试用例它没有在时间限制内执行并且对于少数测试用例我得到了错误的答案

1

After 网格中的每个值都是其 Before 值和其左侧和/或上方的所有 Before 值的总和。 在图中:

  • B是红色区域内所有Before值的总和,
  • Y是绿色和红色区域中所有之前值的总和,
  • X是蓝色和红色区域中所有之前值的总和,并且
  • A是紫色、蓝色、绿色和红色区域中所有之前值的总和。

由于XYB重叠,添加XY将使B计数两次。 因此,如果我们从A开始,减去XY ,然后加上B (以抵消加倍),我们得到A的 Before 值,如下所示: A' = A - X - Y + B

现在我们知道了,代码非常简单:

def before(after)
  before = []
  after.each_with_index do |row,j|
    before[j] = []
    row.each_with_index do |v,i|
      up = j <= 0 ? 0 : after[j-1][i]
      left = i <= 0 ? 0 : after[j][i-1]
      up_left = i <= 0 || j <= 0 ? 0 : after[j-1][i-1]
      before[j][i] = v - up - left + up_left
    end
  end
  before
end

这只是提到了组织@Ouroborus 出色答案的计算的另一种方法。

认为

after = [
  [ 2,  5,  4,  5],
  [ 7, 17, 13, 10],
  [11, 19, 14, 15]
]

通过首先构造以下数组,从after我们避免了检查元素是否在after的第一行或第一列中的需要。

aft = [
  [0,  0,  0,  0,  0],
  [0,  2,  5,  4,  5],
  [0,  7, 17, 13, 10],
  [0, 11, 19, 14, 15]
] 

这是因为,对于任何iji > 0j > 0 ,可以看出:

aft[i][j] = before[i-1][j-1] + aft[i][j-1] + aft[i-1][j] - aft[i-1][j-1]

意思是:

before[i-1][j-1] = aft[i][j] - aft[i][j-1] - aft[i-1][j] + aft[i-1][j-1]

数组aft不需要实际构造,因为我们可以使用方法返回元素aft[i][j]

def aftmap(after, i, j)
  i.zero? || j.zero? ? 0 : after[i-1][j-1]
end

aftmap(after, 0, 0) #=>  0
aftmap(after, 1, 0) #=>  0
aftmap(after, 0, 1) #=>  0
aftmap(after, 2, 2) #=> 17
aftmap(after, 3, 4) #=> 15

这可以以如下方法实现。

def before(after)
  nrows = after.size
  ncols = after.first.size
  (1..nrows).each_with_object(Array.new(nrows) { Array.new(ncols) }) do |i,before|
    (1..ncols).each do |j|
      before[i-1][j-1] = aftmap(after,i,j) - aftmap(after,i,j-1) -
        aftmap(after,i-1,j) + aftmap(after,i-1,j-1)
    end
  end
end 
before(after)
  #=> [[2,  3, -1,  1],
  #    [5,  7, -3, -4],
  #    [4, -2, -1,  4]] 

线

(1..nrows).each_with_object(Array.new(nrows) { Array.new(ncols) }) do |i,before|

可以写

(1..nrows).each_with_object([]) do |i,before|

但我希望前者更有效,因为它避免了before不断扩大数组的需要。

在涉及 arrays 描述矩形网格的其他情况下(例如 Mindcraft 游戏),可以通过概念上在第一行之前和/或最后一行之后添加一行,和/或在第一列之前和/或最后之后。

如果您使用的是 Java,这是代码

通过使用基本方法

私有 static List<List> beforeFromAfter()

    List<List<Integer>> after = Arrays.asList(Arrays.asList(2,5), Arrays.asList(7,17));


    int s=0;
    List<List<Integer>> before = new ArrayList<List<Integer>>();
    for (int i = 0; i<=after.size()-1; i++) {
        
        List<Integer> bRow = new ArrayList<Integer>();
        for (int j=0; j<=after.get(i).size()-1; j++) {
            //bRow.add(j,after.get(i).get(j));
            if(i<1 && j<1) {
                bRow.add(j,after.get(i).get(j));
                s=s+after.get(i).get(j);
            } else if(i>0 && j>0) {
                bRow.add(j,after.get(i).get(j)-s);
            } else {
                bRow.add(j,after.get(i).get(j)-after.get(0).get(0));
                s=s+after.get(i).get(j)-after.get(0).get(0);
            }
            
        }
        
        before.add(i, bRow);
    }
    return before;
}

在 java 中尝试了一些东西。 只需将矩阵、n 和 m 作为方法中的参数传递。 它将返回您之前的矩阵。

public static int[][] getAfterMarix(int[][] before,int n, int m)
{
    int initiate = before[0][0];
    int temp = initiate;
    for(int i=0; i<n ;i++)
    {
        for(int j=0;j<m;j++)
        {
            if(before[i][j]!=initiate)
            {
                if(before[i][j] == before[n-1][m-1])
                {
                    before[i][j] = Math.abs(temp - before[i][j]) ;
                }
                else
                {
                    temp += before[i][j];
                    before[i][j] -= initiate; 
                }
            }
        }
    }
    return before;
}

希望这可以进一步简化这个问题。

vector<vector<int>> getBeforeMatrix(vector<vector<int>> after) {
  auto before = after;
  
  int maxRows = after.size();
  int maxCols = after[0].size();

  for (int row = 0; row < maxRows; row++) {
    for(int col = 0; col < maxCols; col++) {
      if (row > 0) before[row][col] -= after[row - 1][col];
      if (col > 0) before[row][col] -= after[row][col - 1];
      if (row > 0 && col > 0) before[row][col] += after[row - 1][col - 1];
    }
  }

  return before;
}

具有 O(N*M) 时间复杂度和 O(1) 空间复杂度的简单解决方案。

function findMatrix(mat) {
    for(let i = 0; i < mat.length; i++)
    {
        for(let j = 0; j < mat[i].length; j++)
        {
            const after = mat[i][j];
            const before = (i - 1 >= 0 ? mat[i - 1][j] : 0) + (j - 1 >= 0 ? mat[i][j - 1] : 0) + (i > 0 && j > 0 ? mat[i - 1][j - 1] : 0);
            mat[i][j] = after - before;
        }
    }

    return mat;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM