岛数二维数组算法

时间:2017-12-09 10:52:57

标签: javascript algorithm

let arr = [[1, 0, 1],
           [1, 0, 0],
           [1, 1, 1]
     ];

我有1岛和0水的阵列。我需要写一个岛柜台。这里有2个1岛1和1个小(singele)。例如,这里有5个单岛

let arr = [[1, 0, 1],
           [0, 1, 0],
           [1, 0, 1]
     ]; 

我写过双循环来吸引数组中的每个项目:

for(let i = 0; i < arr.length; i++){
    for(let x = 0; x < arr[i].length; x++){
         if(...){}
    }
 }

我需要为此编写сondition。请帮帮我。

4 个答案:

答案 0 :(得分:3)

您可以使用计数器并检查所有相邻项目,并使用实际计数器更新元素。

function check(array) {

    function test(array, i, j, value) {
        if (array[i] && array[i][j] === -1) {
            array[i][j] = value;
            test(array, i -1, j, value);
            test(array, i + 1, j, value);
            test(array, i, j - 1, value);
            test(array, i, j + 1, value);
            return true;
        }
    }
    var value = 1;

    array.forEach(a=> a.forEach((b, i, bb) => bb[i] = -b));
    array.forEach((a, i, aa) => a.forEach((b, j) => test(aa, i, j, value) && value++));
    document.getElementById('out').innerHTML += array.map(a => a.join(' ')).join('\n') + '<hr>';
    return value - 1;
}

console.log(check([[1, 0, 1], [1, 0, 0], [1, 1, 1]]));
console.log(check([[1, 0, 1], [0, 1, 0], [1, 0, 1]]));
<pre id="out"></pre>

答案 1 :(得分:1)

我喜欢这个问题。这是一个基本的问题。因此,就我能想到的而言,值得一个有效的算法。我认为这是递归的呼声。

/**
 * function to resolve islands
 * @param  {Array} map     - the world map we provide
 * @param  {Array} islands - 2D array considiting of island arrays each
 *                           holding island coordinates. Defaults to []
 * @return {Array} islands - "
**/
function resolveIslands(map, islands = []){

  /**
   * function to take a coordinate and split 4 neighboring coordinates into 1s and 0s
   * @param  {Number} r - 0 indexed row value
   * @param  {Number} c - 0 indexed column value
   * @return {Array}    - coordinates of 0s and 1s split in the form of [[0s],[1s]]
  * */
  function splitRoutes(r,c){
    return [[r-1,c],[r,c-1],[r+1,c],[r,c+1]].reduce((p,[r,c]) => map[r]    === void 0 ||
                                                                 map[r][c] === void 0 ? p
                                                                                      : map[r][c] ? (p[1].push([r,c]),p)
                                                                                                  : (p[0].push([r,c]),p), [[],[]]);
  }
  
  /**
   * function to take a coordinate and solve the island if the coordinate is 1
   * @param {Number} r     - 0 index row value
   * @param {Number} c     - 0 index column value
   * @param {Array} island - An array of arrays of coordinates representing the
                             currently resolved island
   * @param {Number} oc    - The number of 1s in da hood
   * @param {Array} tz     - Gradually becoming all available zeros in the map
                             initially []
   * @return {Undefined}   - Full of side effects :)
  * */
  function scan(r, c, island = [], oc = 0, tz = []){
    var [toZeros,toOnes] = splitRoutes(r,c);
    tz.push(...toZeros);
    switch (map[r][c]) {
      case 1: !island.length && islands.push(island);
              oc += toOnes.length;
              map[r][c] = void 0;
              island.push([r,c]);
              toOnes.forEach(([r,c]) => scan(r,c,island,--oc,tz));
              !oc && tz.forEach(([r,c]) => map[r][c] === 0 && scan(r,c,island,oc,tz));
              break;
      case 0: map[r][c] = void 0;
              toOnes.forEach(([r,c]) => map[r][c] === 1 && scan(r,c));
              tz.forEach(([r,c]) => map[r][c] === 0 && scan(r,c));
              break;
    }
  }
  scan(0,0);
  return islands;
}



let arr = [[1, 0, 1],
           [1, 0, 0],
           [1, 1, 1]
          ],
    brr = [[1, 0, 1, 1, 1],
           [0, 1, 0, 0, 1],
           [1, 0, 1 ,1, 0],
           [0, 0, 0, 0, 1],
           [1, 1, 0, 1, 1]
          ];

console.log(JSON.stringify(resolveIslands(arr)));
console.log(JSON.stringify(resolveIslands(brr)));

primaryRoutes(r,c)实用程序函数获取一个坐标并返回我们可以在数组中访问的路径。保持1s的路由优先,0s的路由被延迟(放在队列的后面),并且忽略地图或之前访问的零点。

每个访问过的单元格都变为void 0,这是一个完美的undefined

这比接受的答案稍慢,但我仍然认为考虑到岛屿坐标也很有效。因此,为了获得找到的岛屿的数量,您需要检查生成的数组的length属性。

答案 2 :(得分:0)

更详细的答案,更容易理解:

function gridToList(grid, rows, column){
  var lg = [];
  var gridString = "<p>";
  for(var z = 0; z < grid.length; z++){
    gridString = gridString.concat("[");
    gridString = gridString.concat(grid[z]);
    lg = lg.concat(grid[z]);
    gridString = gridString.concat("]<br/>");
    gridString = gridString.concat("</p>");
  }
  var el = document.getElementById("initialData");
  if(el){
      el.innerHTML = "rows:" + rows + "<br>" +
    "column:" + column + "<br>" +
    "grid:" + gridString + "<br>";
  }
  return lg
}

function numberAmazonGoStores(rows, column, grid)
{
  var idm = {};

  lg = gridToList(grid, rows, column);

  for(var z = 0; z < lg.length; z++){
    if(lg[z]){
      idm[z] = 1;
    }
  }

  var findNeighbors = function(b) {

    var currentBuilding = parseInt(b);
    var currRow = Math.floor(currentBuilding/column);

    //remove value from map so we dont re-traverse it.
    delete idm[currentBuilding];

    var u,d,l,r;

    // u = - column if > 0
    u = currentBuilding - column;
    if(idm[u]) {
      findNeighbors(u);
    }

    // d = + column if < column*rows
    d = currentBuilding + column;
    if(idm[d]) {
      findNeighbors(d);
    }

    // l = - 1 if > 0 && same row;
    l = currentBuilding - 1;
    var lRow = Math.floor(l/column);
    if(lRow === currRow && idm[l]) {
      findNeighbors(l);
    }

    // r = + 1 if < row && same row;
    r = currentBuilding + 1;

    var rRow = Math.floor(r/column);
    if(rRow === currRow && idm[r]) {
      findNeighbors(r);
    }
  }

  var clusters = 0;
  // loop over non traversed values in map
  for(p in idm){
    if(idm[p]){
      findNeighbors(p);
    }
    clusters += 1;
  }
  console.log("grid size = " + lg.length);
  console.log("total clusters found: " + clusters)
  return clusters;
}

g = [
[1,1,1,1],
[1,1,1,1],
[0,0,0,0],
[0,1,0,1]
]
numberAmazonGoStores(4,4,g);

g2 = [
[1,1,0,0,0],
[0,0,0,1,1],
[0,1,0,0,0],
[1,0,1,1,0],
[0,1,0,0,1],
[1,0,1,0,1],
[0,1,0,1,0]
];
numberAmazonGoStores(7,5,g2);

答案 3 :(得分:0)

const map = [
  [1, 0, 0, 0, 1],
  [0, 0, 1, 0, 0],
  [0, 1, 0, 0, 1],
  [0, 1, 1, 1, 1],
  [0, 0, 0, 1, 1]
];

function findIslands(arr) {
  let rows = arr.length,
    cols = arr[0].length; // matrix dimentions

  let islands = 0;
  let eaten = []; // connected islands on the latest iterations

  let left = 0, // island on the left
    up = 0; // island on the right

  for (let row = 0; row < rows; row++) {
    for (let col = 0; col < cols; col++) {
      if (!arr[row][col]) {
        continue; // skip zero (water)
      }
      left = col > 0 ?
        arr[row][col - 1] :
        0;

      up = row > 0 ?
        arr[row - 1][col] :
        0;
      if (!left && !up) { // new island starts if there is water on the left and up
        islands++;
        arr[row][col] = islands; // give a number to island 
      } else if (left && up && left !== up) { //upper island is not seperate
        arr[row][col] = left;
        eaten.push(up)
      } else if (left) {
        arr[row][col] = left; // island continues previous island to the right
      } else if (up) {
        arr[row][col] = up; // island continues previous island
      }
    }
  }
  console.table(arr)
  return islands - eaten.length;
}

console.log('найдено островов ', findIslands(map))