簡體   English   中英

如何在 javascript 中生成螺旋矩陣?

[英]how to generate spiral matrix in javascript?

我正在嘗試在 javascript 中生成螺旋矩陣。

question給定一個integer的A,生成一個由1到A^2的元素按螺旋順序填充的方陣。

輸入:3

 [   [ 1, 2, 3 ],
     [ 8, 9, 4 ],
     [ 7, 6, 5 ]   ]

input is 4

 [   [1, 2, 3, 4],
     [12, 13, 14, 5],
     [11, 16, 15, 6],
     [10, 9, 8, 7]   ]

我的方法是創建具有0值的2d數組,然后它們將填充值。

 let generateMatrix = function(A) { let arr = [], counter = 1; for (let i = 0; i < A; i++) { let items = [] for (let j = 0; j < A; j++) { items.push(0) } arr.push(items) } var spiralMatrix = function(arr) { if (arr.length > 1) { for (let i = 0; i < arr[0].length; i++) { arr[0][i] = counter++; } } return arr } return spiralMatrix(arr) } console.log(generateMatrix(2))

這段代碼應該做你想做的。

// This is your Editor pane. Write your JavaScript hem and
// use the command line to execute commands
let generateMatrix = function(A) {
  let arr = [],
    counter = 1;
  for (let i = 0; i < A; i++) {
    let items = [];
    for (let j = 0; j < A; j++) {
      items.push(0);
    }
    arr.push(items);
  }

  var spiralMatrix = function(arr) {
    let count = 1;
    let k = 0; // starting row
    let m = arr.length; // ending row
    let l = 0; // starting column
    let n = arr[0].length; //ending column

    while (k < m && l < n) {
      // top
      for (var i = l; i < n; i++) {
        arr[k][i] = count;
        count++;
      }
      k++;

      // right
      for (var i = k; i < m; i++) {
        arr[i][n - 1] = count;
        count++;
      }
      n--;

      // bottom
      if (k < m) {
        for (var i = n - 1; i >= l; i--) {
          arr[m - 1][i] = count;
          count++;
        }
        m--;
      }

      // left
      if (l < n) {
        for (var i = m - 1; i >= k; i--) {
          arr[i][l] = count;
          count++;
        }
        l++;
      }
    }
    return arr;
  };
  return spiralMatrix(arr);
};

console.log(generateMatrix(4));

您可以對每條邊進行循環並循環,直到沒有更多范圍可用。

 function spiral(length) { var upper = 0, lower = length - 1, left = 0, right = length - 1, i = 0, j = 0, result = Array.from({ length }, _ => []), value = 1; while (true) { if (upper++ > lower) break; for (; j < right; j++) result[i][j] = value++; if (right-- < left) break; for (; i < lower; i++) result[i][j] = value++; if (lower-- < upper) break; for (; j > left; j--) result[i][j] = value++; if (left++ > right) break; for (; i > upper; i--) result[i][j] = value++; } result[i][j] = value++; return result; } var target = document.getElementById('out'), i = 10; while (--i) target.innerHTML += spiral(i).map(a => a.map(v => v.toString().padStart(2)).join(' ')).join('\\n') + '\\n\\n';
 <pre id="out"></pre>

這在某些方面與我對另一個問題的回答相反。 我們可以通過切出第一行並將其添加到旋轉剩余數字的遞歸調用結果的結果來遞歸地構建它:

 const reverse = a => [...a] .reverse (); const transpose = m => m [0] .map ((c, i) => m .map (r => r [i])) const rotate = m => transpose (reverse (m)) const makeSpiral = (xs, rows) => xs .length < 2 ? [[... xs]] : [ xs .slice (0, xs .length / rows), ... rotate(makeSpiral (xs .slice (xs .length / rows), xs.length / rows)) ] const range = (lo, hi) => [...Array (hi - lo + 1)] .map ((_, i) => lo + i) const generateMatrix = (n) => makeSpiral (range (1, n * n), n) console .log (generateMatrix (4))

敏銳的眼光會注意到這里的rotate與舊問題不同。 transpose (reverse (m))返回輸入矩陣的順時針旋轉版本。 reverse (transpose (m))返回逆時針旋轉的一個。 類似地,這里我們在包含它之前旋轉遞歸調用的結果; 而在另一個問題中,我們對矩陣的旋轉版本進行了遞歸。 由於我們正在逆轉該過程,因此應該很清楚原因。

主要函數是makeSpiral ,它接受一個數組和要螺旋的行數,並返回螺旋矩陣。 (如果rows不是數組長度的一個因素,則行為可能會很瘋狂。) generateMatrix只是它的一個薄包裝器,通過生成初始數組(使用range )並將其傳遞給makeSpiral來處理您的方形情況。

請注意makeSpiral如何makeSpiral除正方形以外的矩形:

makeSpiral ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], 2) //=>
// [
//   [ 1,  2,  3,  4,  5,  6], 
//   [12, 11, 10,  9,  8,  7]
// ]

makeSpiral ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], 3) //=>
// [
//   [ 1,  2,  3,  4], 
//   [10, 11, 12,  5], 
//   [ 9,  8,  7,  6]
// ]

makeSpiral ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], 4) //=>
// [
//   [ 1,  2,  3], 
//   [10, 11,  4], 
//   [ 9, 12,  5], 
//   [ 8,  7,  6]
// ]

makeSpiral ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], 6) //=>
// [
//   [ 1, 2], 
//   [12, 3], 
//   [11, 4], 
//   [10, 5], 
//   [ 9, 6], 
//   [ 8, 7]
// ]

其他函數—— rangereversetransposerotate ——是用於處理數組或矩陣的通用實用函數。

這是一種解決方案。

我將當前的“移動方向”保留在dxdy ,以便下一個矩陣元素索引由x+dxy+dy

如果下一個項目已經填滿或超出范圍,我會順時針改變這個方向。 否則,我用下一個值填充它。

 const size = 6; const matrix = Array(size).fill().map(() => Array(size).fill(0)); let x = -1; let y = 0; let dx = 1; let dy = 0; function changeDirection() { if (dx === 1) { dx = 0; dy = 1; } else if (dy === 1) { dy = 0; dx = -1; } else if (dx === -1) { dx = 0; dy = -1; } else { dx = 1; dy = 0; } } for (let i = 0; i < size * size; i++) { const yNext = y + dy; const xNext = x + dx; const nextRow = matrix[yNext] || []; const nextItemContent = nextRow[xNext]; if (nextItemContent === undefined || nextItemContent > 0) { changeDirection(); i--; continue; } y = yNext; x = xNext; matrix[y][x] = i + 1; } const result = document.getElementById('result'); matrix.forEach(row => { row.forEach(value => { result.innerHTML += value.toString().padStart(3); }); result.innerHTML += '\\n'; });
 <pre id="result"></pre>

我正在計算索引,每個數字都應該放在一個線性數組中

 console.clear(); Array.prototype.range = function(a, b, step) { step = !step ? 1 : step; b = b / step; for(var i = a; i <= b; i++) { this.push(i*step); } return this; }; const spiral = function(dimen) { "use strict"; const dim = dimen; const dimw = dim; const dimh = dim; var steps = [1, dimh, -1, -dimh]; var stepIndex = 0; var count = 1; var countMax = dimw var dec = 0 var index = 0; var arr = []; arr = arr.range(1, dimh * dimw) const newArr = arr.reduce((coll, x, idx) => { index += steps[stepIndex] coll[index-1] = idx+1; if (count === countMax) {count = 0; stepIndex++; dec++;} if (dec === 1) {dec = -1; countMax--} if (stepIndex == steps.length) {stepIndex = 0} count++; return coll; }, []); var ret = [] while (newArr.length) { ret.push(newArr.splice(0,dimw)) } return ret } console.log(spiral(3)) console.log(spiral(4)) console.log(spiral(5))

 var n=14; // size of spiral var s=[]; // empty instruction string function emp() {} // no move function xpp() {xp++;} // go right function xpm() {xp--;} // go left function ypp() {yp++;} // go down function ypm() {yp--;} // go up var r=[xpp,ypp,xpm,ypm]; // instruction set s.push(emp); // push 'no move' (used for starting point) var c=n-1; while (c-->0) s.push(r[0]); // push first line - uses a different rule for (var i=1;i<2*n-1;i++) { // push each leg c=Math.floor((2*ni)/2); while (c-->0) s.push(r[i%4]); } var sp=new Array(n); // spiral array for (var i=0;i<n;i++) sp[i]=new Array(n); var xp=0; // starting position var yp=0; for (var i=0;i<n*n;i++) { s[i](); // execute next instruction sp[yp][xp]=i+1; // update array } for (var i=0;i<n;i++) console.log(sp[i].toString()); // log to console

這段代碼制作了一個函數宏來生成一個運行序列,例如:

'right4, down4, left4, up3, right3, down2, left2, up1, right1

然后實現它。

這是 leetcode 中 Spiral Matrix 的解決方案,也許這會有所幫助

https://leetcode.com/problems/spiral-matrix/

 var spiralOrder = function(matrix) { if (matrix.length == 0) { return []; } let result = []; let rowStart = 0; let rowEnd = matrix.length - 1; let colStart = 0; let colEnd = matrix[0].length - 1; while (true) { // top for (let i = colStart; i <= colEnd; i++) { result.push(matrix[rowStart][i]); } rowStart++; if (rowStart > rowEnd) { return result; } // right for (let i = rowStart; i <= rowEnd; i++) { result.push(matrix[i][colEnd]); } colEnd--; if (colEnd < colStart) { return result; } // bottom for (let i = colEnd; i >= colStart; i--) { result.push(matrix[rowEnd][i]); } rowEnd--; if (rowEnd < rowStart) { return result; } // left for (let i = rowEnd; i >= rowStart; i--) { result.push(matrix[i][colStart]); } colStart++; if (colStart > colEnd) { return result; } } return result; }; console.log( spiralOrder([[2, 3, 4], [5, 6, 7], [8, 9, 10], [11, 12, 13], [14, 15, 16]]) ); console.log(spiralOrder([[7], [9], [6]])); console.log(spiralOrder([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])); console.log(spiralOrder([[1, 2, 3], [4, 5, 6], [7, 8, 9]]));

這是我只使用一個 for 循環的答案 -

function matrix(n) {
  const arr = [];
  let row = 0;
  let column = 0;
  let counter = 1;
  let edge = n - 1;

  let leftToRightRow = false;
  let topToBottomCol = false;
  let rightToLeftRow = false;
  let bottomToTopCol = false;

  for (i = 0; i < n * n; i++) {
    if (column <= edge && !leftToRightRow) {
      if (!Array.isArray(arr[row])) {
        arr[row] = []; // if array is not present at this index, then insert one
      }
      arr[row][column] = counter;
      if (column == edge) {
        row = row + 1;
        leftToRightRow = true;
      } else {
        column = column + 1;
      }
      counter = counter + 1;
    } else if (column === edge && !topToBottomCol) {
      if (!Array.isArray(arr[row])) {
        arr[row] = []; // if array is not present at this index, then insert one
      }
      arr[row][column] = counter;
      if (row === edge) {
        column = column - 1;
        topToBottomCol = true;
      } else {
        row = row + 1;
      }
      counter = counter + 1;
    } else if (column >= 0 && !rightToLeftRow) {
      arr[row][column] = counter;
      if (column === 0) {
        row = row - 1;
        rightToLeftRow = true;
      } else {
        column = column - 1;
      }
      counter = counter + 1;
    } else if (row >= n - edge && !bottomToTopCol) {
      arr[row][column] = counter;
      if (row === n - edge) {
        column = column + 1;
        bottomToTopCol = true;
        //setting these to false for next set of iteration
        leftToRightRow = false;
        topToBottomCol = false;
        rightToLeftRow = false;
        edge = edge - 1;
      } else {
        row = row - 1;
      }
      counter = counter + 1;
    }
  }
  return arr;
}

解決方案是在 C++ 中實現的,但只有邏輯問題你可以用任何語言來實現:

vector<vector<int> > Solution::generateMatrix(int A) {
    vector<vector<int>> result(A,vector<int>(A));
    int xBeg=0,xEnd=A-1;
    int yBeg=0,yEnd=A-1;
    int cur=1;
    while(true){
        for(int i=yBeg;i<=yEnd;i++) 
            result[xBeg][i]=cur++;

        if(++xBeg>xEnd) break;

        for(int i=xBeg;i<=xEnd;i++) 
            result[i][yEnd]=cur++;

        if(--yEnd<yBeg) break;

        for(int i=yEnd;i>=yBeg;i--) 
            result[xEnd][i]=cur++;

        if(--xEnd<xBeg) break;

        for(int i=xEnd;i>=xBeg;i--) 
            result[i][yBeg]=cur++;
            
        if(++yBeg>yEnd) break;
    }
    return result; 
}

c#中的解決方案:

為了解決這個問題,我們對每個移動方向使用循環

     public IList<int> SpiralOrder(int[][] matrix) {
        var result = new List<int>();
            var n = matrix[0].Length;
            var m = matrix.Length;
            var i = 0;
            var j = 0;
            var x = 0;
            var y = 0;

            while (true)
            {
                //left to right moving:
                while (x <= n - 1 - i)
                {
                    result.Add(matrix[y][x]);
                    x++;
                }
                if (result.Count == n * m)
                    return result;
                x--;y++;

                //up to down moving:
                while (y <= m - 1 - j)
                {
                    result.Add(matrix[y][x]);
                    y++;
                }
                if (result.Count == n * m)
                    return result;
                y--;x--;

                //right to left moving:
                while (x >= j)
                {
                    result.Add(matrix[y][x]);
                    x--;
                }
                if (result.Count == n * m)
                    return result;
                x++;y--;

                //down to up moving:
                while (y > j)
                {
                    result.Add(matrix[y][x]);
                    y--;
                }
                if (result.Count == n * m)
                    return result;
                y++;x++;
                i++;
                j++;                
            }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM