【问题标题】:Minimise Manhattan distance between x and y in a matrix最小化矩阵中 x 和 y 之间的曼哈顿距离
【发布时间】:2019-10-20 05:32:49
【问题描述】:

我正在尝试解决一个涉及曼哈顿距离和矩阵的问题。

问题: 给定一个二维矩阵,其中每个单元格可能包含字符“0”或“x”或“y”。求 x 和 y 之间的最小曼哈顿距离。

x 和 y 之间的曼哈顿距离为 |X(x) - X(y)| + |Y(x) - Y(y)|。 X & Y 分别代表行号、列号。包含矩阵中字符的单元格。

例子:

[ x, 0, 0, 0 ]
[ 0, y, 0, y ]
[ x, x, 0, 0 ]
[ 0, y, 0, 0 ]

是给定的,我们必须计算 x 和 y 之间的最小曼哈顿距离;在这种情况下,它是 1(在 (3,2) 和 (4,2) 之间)。

蛮力方法相当于 O((m * n)^2) 时间,如何优化到至少 O(m * n)?

【问题讨论】:

    标签: algorithm matrix data-structures


    【解决方案1】:

    这是一个经典的图论问题。

    首先请注意,曼哈顿距离只是网格上从一个单元格到另一个单元格的最短路径。

    然后将标有x 的节点添加到队列中并执行BFS 直到您访问某个y 节点并且到该节点的距离将是答案。

    复杂度:O(n*m)

    示例代码(C++):

    int n = 4;
    const int inf = 1234567890;
    vector<string>M = {"x000","0y0y","xx00","0y00"};
    vector<vector<int>>D(n, vector<int>(n,inf));
    queue<array<int,2>>Q;
    
    for(int i=0; i<n; i++)
    for(int j=0; j<n; j++)
        if(M[i][j]=='x')
    {
        Q.push({i,j});
        D[i][j]=0;
    }
    
    int res = inf;
    
    while(!Q.empty())
    {
        int row = Q.front()[0];
        int col = Q.front()[1];
        if(M[row][col]=='y')
        {
            res=D[row][col];
            break;
        }
        Q.pop();
    
        int dr[] = {-1,1,0,0};
        int dc[] = {0,0,-1,1};
    
        for(int k=0; k<4; k++)
        {
            int r = row + dr[k];
            int c = col + dc[k];
            if(min(r,c) >=0 && max(r,c) < n && D[r][c]==inf)
            {
                D[r][c]=D[row][col]+1;
                Q.push({r,c});
            }
        }
    }
    
    cout<<res;
    

    【讨论】:

      【解决方案2】:

      不使用图论

      • 将任意x_i 的坐标放入集合x
      • 将任意y_j 的坐标放入集合y
      • 对 x 和 y 的笛卡尔积应用距离,同上 考虑d(x_i, y_j) 为所有ij
      • 保持最小

      如果x_s 的大小为Xy_s 的大小为Y:在O(x_sy_s) 中运行(假设您事先知道x_iy_j 的位置...(O(mn)否则)

      let {x,y} = `x000,0y0y,xx00,0y00`.replace(/,/g,'').split('').reduce((acc,v,id)=>{
          let y = id%4;
          let x = (id-y)/4
          if(v=='x'||v=='y'){
              acc[v].push([x,y]);
          }
          return acc;
      },{x:[],y:[]})
      let d = (a,b)=>Math.abs(a[1]-b[1])+Math.abs(a[0]-b[0]);
      console.log('dist:', Math.min(...x.map(v=>Math.min(...y.map(w=>d(v,w))))))

      【讨论】:

        【解决方案3】:

        对于矩阵的每个单元格,最小曼哈顿距离就是到左边最近的 x 和上面最近的 y 的距离,或者到左边最近的 x 和上面最近的 y 的距离。 O(n*m) 扫描行和列的时间,O(n) 内存跟踪每列中最近的 x 和 y(与广度优先搜索的 O(n*m) 最坏情况相比)。

        def distance(M):
            rows = len(M)
            cols = len(M[0])
            above_x = cols * [-1]
            above_y = cols * [-1]
            res = float('inf')
            for row in range(rows):
                left_x = -1
                left_y = -1
                for col in range(cols):
                    # track the nearest x and y to the left and above
                    if M[row][col] == 'x':
                        above_x[col] = row
                        left_x = col
                    if M[row][col] == 'y':
                        above_y[col] = row
                        left_y = col
        
                    # the shortest distance is just the two distances added together
                    if left_y > -1 and above_x[col] > -1:
                        res = min(res, (col - left_y) + (row - above_x[col]))
                    if left_x > -1 and above_y[col] > -1:
                        res = min(res, (col - left_x) + (row - above_y[col]))
            return res
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-05-24
          • 2023-03-11
          • 1970-01-01
          • 2017-01-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-18
          相关资源
          最近更新 更多