代码之家  ›  专栏  ›  技术社区  ›  Maheer Ali

如何在表示矩形的数组中获取与某个索引成对角线的元素

  •  0
  • Maheer Ali  · 技术社区  · 6 年前

    考虑一个数组,其长度总是两个数的乘积。对于下面的数组 l 是4岁 w 5 .

    还有一个给定的索引。我想得到包含元素的两个数组,它们位于通过特定索引的对角线上。

    [
        0,  1,  2,  3,  4
        5,  6,  7,  8,  9
        10, 11, 12, 13, 14
        15, 16, 17, 18, 19
    ]  
    
    index = 7 => [3, 7, 11, 15] and [1, 7, 13, 19]
    index = 16 => [4, 8, 12, 16] and [10, 16]
    index = 0 => [0, 6, 12, 18] and [0]
    

    我试过以下几点:

    let arr = Array(20).fill().map((x,i) => i);
    
    function getDias(arr, l, w, ind){
      let arr1 = [];
      let arr2 = [];
      
      for(let i = 0;i<l;i++){
        arr1.push(arr[ind + (i * w) + i])
        arr1.push(arr[ind - (i * w) - i])
        arr2.push(arr[ind + (i * w) + i])
        arr2.push(arr[ind - (i * w) - i])
      }
      const remove = arr => [...new Set(arr.filter(x => x !== undefined))];
      return [remove(arr1),remove(arr2)];
    
    }
    console.log(getDias(arr, 4, 5, 7))

    代码有两个问题。结果中的两个数组是相同的。第二,它们不正常。

    注: 我不想用 sort() 重新排列数组。而且我也不想循环所有20个元素。只想得到对角线行的元素

    0 回复  |  直到 6 年前
        1
  •  4
  •   Trentium    6 年前

    一些数学(如模、整数除法和极小值)可以找到从左到右(LTR)和从右到左(RTL)的对角线的起始行和列,从而节省了向后迭代寻找起点的复杂性。然后,使用那些开始的行和列,简单地迭代,直到超出数组的高度和宽度界限。

    let arr = Array(20).fill().map((x, i) => i);
    
    function diagonals(arr, h, w, n) {
      var nRow = Math.floor(n / w);
      var nCol = n % w;
    
      let LTR = [];
      for (let r = nRow - Math.min(nRow, nCol), c = nCol - Math.min(nRow, nCol); r < h && c < w; r++, c++) LTR.push(arr[r * w + c]);
    
      let RTL = [];
      for (let r = nRow - Math.min(nRow, w - nCol - 1), c = nCol + Math.min(nRow, w - nCol - 1); r < h && 0 <= c; r++, c--) RTL.push(arr[r * w + c]);
    
      return [LTR, RTL];
    }
    

    样本运行。。。

    diagonals(arr, 4, 5, 7);  // returns ==> [[1, 7, 13, 19], [3, 7, 11, 15]]
    diagonals(arr, 4, 5, 15); // returns ==> [[15], [3, 7, 11, 15]]
    

    编辑:关于 arr 价值与指数。

    还有一点需要澄清。问题表明“还有一个给定的索引。我想得到两个数组,其中包含的元素位于通过该特定索引的对角线上。”如果正在寻找矩形数组的索引,而不是 ,则无需建造 ,然后 function push 语句可以更改为。。。

    • function diagonals(h, w, n)
    • LTR.push(r * w + c)
    • RTL.push(r * w + c)
        2
  •  1
  •   Phenomenal One    6 年前

    请尝试以下代码

    let arr = Array(20).fill().map((x,i) => i);
    
    function getDias(arr, l, w, ind){
      let arr1 = [];
      let arr2 = [];
      n = l*w;
      lVal = Math.floor(ind/w);
      rVal = ind%w;
      temp1  = lVal;
      temp2  = rVal;
      while(temp1>=0 && temp2>=0){
        val = ((w*temp1) + temp2);
        arr1.unshift(arr[val]);  
        temp1--;
        temp2--;
      }
      temp1  = lVal;
      temp2  = rVal;
      temp1++;
      temp2++;
      while(temp1<l && temp2<w){
        val = ((w*temp1) + temp2);
        arr1.push(arr[val]);  
        temp1++;
        temp2++;
      }
    
       
      console.log(arr1);
      temp1  = lVal;
      temp2  = rVal;
      while(temp1>=0 && temp2<w){
        val = ((w*temp1) + temp2);
        arr2.unshift(arr[val]);  
        temp1--;
        temp2++;
      }
      
      temp1  = lVal;
      temp2  = rVal;
      temp1++;
      temp2--;
      while(temp1<l && temp2>=0){
        val = ((w*temp1) + temp2);
        arr2.push(arr[val]);  
        temp1++;
        temp2--;
      }
    
      console.log(arr2);
    
    }
    getDias(arr, 4, 5, 7);
    getDias(arr, 4, 5, 16);
    getDias(arr, 4, 5, 0);

    这个想法是计算l_val和r_val。

    l_val = index/w
    r_val = index%w
    

    现在arr[l_val][r_val]标记了l_val*w+r_val在矩阵中的位置

    接下来是4个步骤:

    1) 从arr[l_val][r_val]开始迭代。从两者中减去1,直到我们到达终点。将其取消移动到数组_1(以维持秩序)

    2) 从[l_val][r_val]开始迭代。两个都加1,直到我们到达终点。把这个推到数组_1。

    3) 从arr[l_val][r_val]开始迭代。从l_val中减去1,再加上1 t r_val,直到我们到达终点。将其取消移动到数组_2(以维持秩序)

    4) 从[l_val][r_val]开始迭代。l_val加1,r_val减1,直到结束。把这个推到array_2。

        3
  •  1
  •   nice_dev    6 年前

    let arr = Array(20).fill().map((x, i) => i);
    
    function getDias(arr, l, w, ind) {
      let arr1 = [];
      let arr2 = [];
      let row = parseInt(ind / w);
      let col = ind - row * w;
      diagIteration(arr, row, col, l, w, -1, arr1);
      diagIteration(arr, row, col, l, w, 1, arr2);
      return [arr1, arr2];
    }
    
    function diagIteration(arr, row, col, l, w, strategy, result) {
      // find the starting row and col to begin with
      while (row - 1 >= 0 && col + strategy >= 0 && col + strategy < w) {
        row--;
        col += strategy;
      }
      // iterate the diagonal elements and add it in result
      strategy *= -1; // since we need to diagonally the reverse way after getting the base indexes to begin with
      for (; row >= 0 && row < l && col >= 0 && col < w; row++, col += strategy) result.push(arr[row * w + col]);
    }
    
    // tests
    for (var i = 0; i < arr.length; ++i) {
      console.log(arr[i] + ' =>', getDias(arr, 4, 5, i));
    }
    • 我们计算 row column 对于特定的给定索引。对于任何给定的索引 一行 会是 index / width 会是 index - row * width .
    • 现在,我们找到要开始的基本索引,并在对角线上迭代,就像是一个2D数组一样。位于任何对角线上的指数可计算为 row * width + column .我们再做一次检查,看看我们是否仍在模拟2D阵列的范围内。