孤岛计数二维数组算法
Posted
技术标签:
【中文标题】孤岛计数二维数组算法【英文标题】:island count two-dimensional array algorithm 【发布时间】:2017-12-09 10:52:57 【问题描述】:let arr = [[1, 0, 1],
[1, 0, 0],
[1, 1, 1]
];
我有数组,其中 1 岛和 0 水。我需要写一个岛屿计数器。这里有 2 岛 1 大和 1 小(单人)。例如这里有 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。请帮帮我。
【问题讨论】:
想要的结果是什么?岛屿的数量?尺寸? 对不起,我忘了写。我需要岛屿数 到目前为止您尝试过什么?你被困在哪里了?您在寻找哪种“条件”? 【参考方案1】:您可以使用计数器并检查所有相邻项目并使用实际计数器更新元素。
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>
【讨论】:
【参考方案2】:我喜欢这个问题。这是一个基本的。因此,就我能想到的而言,应该有一个有效的算法。我认为它需要递归。
/**
* 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)
实用函数接受一个坐标,并在数组中返回我们接下来可以访问的路线。包含 1 的路线优先,包含 0 的路线延迟(放在队列的后面),地图外或之前访问过的 0 的路线将被忽略。
每个访问的单元格都变成void 0
,这是一个完美的undefined
。
这比公认的答案稍慢,但考虑到您也获得了岛屿坐标,我仍然认为它是有效的。因此,为了获得找到的岛屿的数量,您需要检查结果数组的 length
属性。
【讨论】:
【参考方案3】:一个更详细的答案,更容易理解:
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);
【讨论】:
解决问题的具体算法是什么? 只有在浏览器中才会更加冗长 @NinaScholz 我称之为递归部门优先搜索。这是来自互联网的一个小sn-p:遍历图表。 ...您可以通过遍历图形的所有顶点轻松地做到这一点,对检查时仍未访问的每个顶点执行算法。图的遍历通常使用两种算法:深度优先搜索 (DFS) 和广度优先搜索 (BFS)。 @LucaKiebel 我说它更冗长主要是因为我没有嵌套循环或链式操作。取而代之的是,我确保每个逻辑部分都分列在不同的行中,以便读者可以更轻松地通过逻辑。对于那些想要快速复制、粘贴和运行的人来说,日志记录和 ui 更新只是节食。【参考方案4】: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))
【讨论】:
请在您的答案中添加一些解释,以便其他人可以从中学习以上是关于孤岛计数二维数组算法的主要内容,如果未能解决你的问题,请参考以下文章