好的,所以这个问题有点笨拙,但我希望这会让事情变得清晰。
我有这个样本2d数组。
$array = array(
array(1, 0, 0, 0, 1, 0, 0, 1),
array(0, 0, 1, 1, 1, 1, 0, 1),
array(0, 1, 1, 0, 1, 0, 0, 0),
array(0, 1, 1, 0, 0, 0, 1, 0),
array(1, 0, 0, 0, 1, 1, 1, 1),
array(0, 1, 1, 0, 1, 0, 1, 0),
array(0, 0, 0, 0, 0, 0, 0, 1)
);
当按行迭代(并用\ n终止每一行),然后对于按列迭代的每一行,它将回显如下:(░░= 0,▓▓= 1)
▓▓░░░░░░▓▓░░░░▓▓
░░░░▓▓▓▓▓▓▓▓░░▓▓
░░▓▓▓▓░░▓▓░░░░░░
░░▓▓▓▓░░░░░░▓▓░░
▓▓░░░░░░▓▓▓▓▓▓▓▓
░░▓▓▓▓░░▓▓░░▓▓░░
░░░░░░░░░░░░░░▓▓
但我想做的是"分析"数组只留下1个连续的形状(最多的#34;单元格"),在这个例子中,结果将是:
░░░░░░░░▓▓░░░░░░
░░░░▓▓▓▓▓▓▓▓░░░░
░░▓▓▓▓░░▓▓░░░░░░
░░▓▓▓▓░░░░░░░░░░
▓▓░░░░░░░░░░░░░░
░░▓▓▓▓░░░░░░░░░░
░░░░░░░░░░░░░░░░
我最初的做法是:
为每个▓▓单元格分配一个唯一的编号(无论是完全随机的,还是当前的迭代编号):
01 02 03
04050607 08
0910 11
1213 14
15 16171819
2021 22 23
24
多次迭代数组:每次迭代,每个▓▓单元格在其邻居中占据最大的唯一数字。循环将无限期地继续,直到在当前状态和先前状态之间没有检测到变化。在最后一次迭代之后,结果将是:
01 21 08
21212121 08
2121 21
2121 24
21 24242424
2121 24 24
24
现在,这一切都归结为计算最多发生的价值。然后,再次迭代,将所有值不是最受欢迎的单元格转换为0,从而得到所需的结果。
但是,对于这样一个简单的任务,我觉得这是一个非常迂回,计算量很大的方法,必须有更好的方法。任何想法都会非常感激,欢呼!
奖励积分:将所有blob划分为一个2D数组数组,按照单元格数排序,这样我们就可以用最小的blob做一些事情
答案 0 :(得分:1)
我只能想到一些小改进:
保留非空字段的链接列表。在步骤2中,您不需要触摸n²矩阵元素,只需触摸链表中的元素即可。根据矩阵的稀疏程度,这可能会少得多。
您只需要比较右,右下,左下和下方向。否则,已从前一行/列检查其他方向。我的意思是:当我比右邻居更大时,我已经可以改变右邻居的号码了。 (同样适用于向下和向右)。这是比赛数量的一半。
答案 1 :(得分:1)
总是好玩,这些问题。之前完成了,所以我在这里转储我的代码,也许你可以使用其中的一些代码。这基本上遵循每个形状,通过观察细胞及其周围的8个细胞,如果它们连接到连接细胞,再看一下等等......
<?php
$shape_nr=1;
$ln_max=count($array);
$cl_max=count($array[0]);
$done=[];
//LOOP ALL CELLS, GIVE 1's unique number
for($ln=0;$ln<$ln_max;++$ln){
for($cl=0;$cl<$cl_max;++$cl){
if($array[$ln][$cl]===0)continue;
$array[$ln][$cl] = ++$shape_nr;
}}
//DETECT SHAPES
for($ln=0;$ln<$ln_max;++$ln){
for($cl=0;$cl<$cl_max;++$cl){
if($array[$ln][$cl]===0)continue;
$shape_nr=$array[$ln][$cl];
if(in_array($shape_nr,$done))continue;
look_around($ln,$cl,$ln_max,$cl_max,$shape_nr,$array);
//SET SHAPE_NR to DONE, no need to look at that number again
$done[]=$shape_nr;
}}
//LOOP THE ARRAY and COUNT SHAPENUMBERS
$res=array();
for($ln=0;$ln<$ln_max;++$ln){
for($cl=0;$cl<$cl_max;++$cl){
if($array[$ln][$cl]===0)continue;
if(!isset($res[$array[$ln][$cl]]))$res[$array[$ln][$cl]]=1;
else $res[$array[$ln][$cl]]++;
}}
//get largest shape
$max = max($res);
$shape_value_max = array_search ($max, $res);
//get smallest shape
$min = min($res);
$shape_value_min = array_search ($min, $res);
// recursive function: detect connecting cells
function look_around($ln,$cl,$ln_max,$cl_max,$nr,&$array){
//create mini array
$mini=mini($ln,$cl,$ln_max,$cl_max);
if($mini===false)return false;
//loop surrounding cells
foreach($mini as $v){
if($array[$v[0]][$v[1]]===0){continue;}
if($array[$v[0]][$v[1]]!==$nr){
// set shape_nr of connecting cell
$array[$v[0]][$v[1]]=$nr;
// follow the shape
look_around($v[0],$v[1],$ln_max,$cl_max,$nr,$array);
}
}
return $nr;
}
// CREATE ARRAY WITH THE 9 SURROUNDING CELLS
function mini($ln,$cl,$ln_max,$cl_max){
$look=[];
$mini=[[-1,-1],[-1,0],[-1,1],[0,-1],[0,1],[1,-1],[1,0],[1,1]];
foreach($mini as $v){
if( $ln + $v[0] >= 0 &&
$ln + $v[0] < $ln_max &&
$cl + $v[1] >= 0 &&
$cl + $v[1] < $cl_max
){
$look[]=[$ln + $v[0], $cl + $v[1]];
}
}
if(count($look)===0){return false;}
return $look;
}
答案 2 :(得分:0)
如果您的阵列大小不是很大并且内存不会成为问题,那么递归解决方案可能会更快。我在这里找到了一个c ++算法: https://www.geeksforgeeks.org/find-length-largest-region-boolean-matrix/