我有一个类型为Animal
的二维数组(用户定义的类型)。我已设置数组,以便随机填充Prey
或Pred
类型Animal
或任何内容(保留null
)。
我的问题是关于接近度,我想知道Prey
是否在Pred
(包括对角线)旁边的空格中。说我有这个:
{null, null, null,
null, Prey, null,
Pred, null, null}
假设我使用:
Animal[][] grid = new Animal[3][3];
如果我只是说:
for (int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
if (grid[i+1][j] == Pred || grid[i+1][j+1] == Pred || grid[i+1][j+1] == Pred
|| grid[i][j+1] == Pred || grid[i-1][j+1] == Pred || grid[i+1][j] == Pred
|| grid[i-1][j] == Pred || grid[i-1][j-1]) == Pred) // Then proximity = true.
}
}
这会非常低效吗?整个数组是否必须通过8次搜索来检查if语句是否返回true?
我需要将数组扩展到几千个&#34;空间&#34;我想要一种不会花费太多时间的方法。
如果这种方式效率低下,任何人都可以建议更好(也许更清洁)的方法吗?
答案 0 :(得分:1)
如果要检查2D数组中的每个可能索引,您似乎必须执行n^2
算法。
您希望确保每个true
语句的优先级为if
这四个条件:
i+1 < grid.length
i-1 >= 0
j+1 < grid[i].length
j-1 >= 0
遵循此伪代码以避免错误:
boolean proximity = false;
for (int i = 0; i < grid.length; i++){
for(int j = 0; j < grid[i].length; j++){
if(grid[i][j] == Pred){ //only care if its a Pred
//now check for Prey
//make sure youre not out of bounds!
if(i+1 < grid.length && grid[i+1][j] == Prey) proximity = true;
else if(i+1 < grid.length && j+1 < grid[i].length && grid[i+1][j+1] == Prey) proximity = true;
//do for rest etc.
}
if(proximity) break;//once found, youre done.
}
}
答案 1 :(得分:0)
for (int i = 0; i < 3; i++){
for(int j = 0; i < 3; j++){
if(grid[i][j] == Pred)
{
if (grid[i][j+1] == Prey || grid[i+1][j-1] == Prey || grid[i+1][j] == Prey
|| grid[i+1][j+1] == Prey ) // Then proximity = true.
}
if(grid[i][j] == Prey)
{
if (grid[i][j+1] == Pred || grid[i+1][j-1] == Pred || grid[i+1][j] == Pred
|| grid[i+1][j+1] == Pred ) // Then proximity = true.
}
}
}
注意双边接近度,如果grid [i] [j]与网格[i + 1] [j + 1]接近,则网格[i + 1] [j + 1]接近格[i] [j]。
此外,您必须牢记矩阵的界限。如果您在最后一栏,请不要检查下面的行,如果您在第一列,请不要检查左侧的列,如果您是,请不要检查右侧的列在最后一栏。 (有了这个方法,你永远不会检查上面的行,所以不要担心上限)
编辑并更正。你还必须注意到bilareal的接近程度。
答案 2 :(得分:0)
你可以创建如下函数:
public boolean containsPreditor(int x, int y, Animal[] grid)
{
boolean outOfBounds = false;
if(x < 0 || x >= grid[0].length)
{
outOfBounds = true;
}
if(y < 0 || y >= grid.length)
{
outOfBounds = true;
}
if(!outOfBounds)
{
return grid[y][x] == Pred;
}
else
{
//space does not exist
return false;
}
}
然后你可以运行3x3网格的方法,或者通过修改循环大小你想要它的大小
boolean proximity = false;
int xIndex; //assign this
int yIndex; //assign this too
for(int i = (yIndex - 1); i <= (yIndex + 1); i++)
{
for(int j = (xIndex - 1); j <= (xIndex + 1); j++)
{
proximity = proximity || containsPreditor(j, i, Animals);
}
}
基本上是相同的,但更容易理解和调试
答案 3 :(得分:0)
我为你做了一夜之间的思考,并意识到通过将电路板表示为一个集合,然后使用位逻辑来组合,可以更快地完成。这种方法特别适用于CPU和CPU缓存,但它确实需要一些前期计算,理想情况下是存储板的方式的变化。如果你不能这样做,那么将需要克服一些开销。但是值得付出努力!
基本算法是:
preyAtRisk = bitCount( squaresAtRisk.bitAnd(squaresWithPrey) )
该算法可以用非常少的条件跳转来实现,现代CPU可以在单个cpu周期中执行64位,并且大多数JVM为Integer.bitCount和Long.bitCount提供内在函数,用一个汇编指令替换它们。因此,许多循环可以在硬件中并行完成。那就是,快!
此算法要求将电路板表示为位集。因此对于3x3电路板,第一个方块将是第一个位,依此类推,直到第九个方块为第九位。
因此你的例子是
{null, null, null,
null, Prey, null,
Pred, null, null}
将由以下两个位集
表示prey = 000 010 000
preds = 000 000 100
然后我们需要将preds位集转换为代表哪些方块有风险的位集。这可以通过预先计算每个正方形的方块将处于危险中的位组来完成。看起来像这样:
dangerZones[0] = 010 110 000
dangerZones[1] = 101 111 000
dangerZones[2] = 010 011 000
...
然后当preds被添加到集合中,或者在它自己的迭代中,可以构建squareAtRisk:
public void setPred( x, y ) {
bitIndex = toBitIndex(x,y)
squaresAtRisk &= dangerZones[bitIndex]
}