我正在尝试使用floodfill
从2d数组中计算零数,但我得到的是ArrayIndexOutOfBoundsException
。这是我到目前为止所做的。我评论了错误的位置。
public class floodfill {
public static int[][] input = new int[][]{
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
public static int count = 0;
public static void main(String[] args) {
int row = input.length;
int col = input[0].length;
System.out.println("" + row);
System.out.println("" + col);
apply(row, col);
}
private static void apply(int x, int y) {
int currentColor = getValueAt(x, y);
if (currentColor == 0) {
count++;
apply(x + 1, y);
apply(x - 1, y);
apply(x, y + 1);
apply(x, y - 1);
}
}
private static int getValueAt(int x, int y) {
if (x < 0 || y < 0 || x > input.length || y > input[x].length) {
return -1;
} else {
return input[x][y];
}
}
}
答案 0 :(得分:1)
除了已经使用数组索引检查指出的错误(在>=
数组长度时终止,而不是在长度超过时),您的递归将永远不会终止并且您将体验到一些非常有趣的堆栈溢出错误。
进入单元格后,您需要将值从0
更改为其他内容(例如1
)。我建议添加visit
方法来处理这个问题:
private static void visit(int x, int y) {
input[x][y] = 1;
}
您可以在apply
块内if
内调用此内容。最后,您应该从第一个节点apply(0, 0)
开始,然后向外工作(x+1, y+1), (x, y+1), (x+1, y)
;从来没有理由从当前索引中减去,因为之前的单元格已经被访问过了。
private static void apply(int x, int y) {
int currentColor = getValueAt(x, y);
if (currentColor == 0) {
visit(x, y);
count++;
apply(x + 1, y + 1);
apply(x + 1, y);
apply(x, y + 1);
}
}
下面运行的这个更新算法的简单可视化(移植到JS以在浏览器中运行,但语法足够相似,您将理解它 - 您可以忽略特定于可视化的代码)。
$(function() {
var input = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
];
var count = 0;
function main() {
var row = 0, col = 0;
apply(row, col);
console.log(count);
};
function apply(x, y) {
var currentColor = getValueAt(x, y);
if (currentColor == 0) {
visit(x, y);
count++;
apply(x + 1, y + 1);
apply(x + 1, y);
apply(x, y + 1);
}
}
function getValueAt(x, y) {
if (x < 0 || y < 0 || x >= input.length || y >= input[x].length) {
return -1;
} else {
return input[x][y];
}
}
function visit(x, y) {
setTimeout(function() {
$(("#child" + x) + y).css("background-color", "pink");
}, 170 * x + 170 * y);
input[x][y] = 1;
}
function visualize() {
for (var i = 0; i < input.length; i++) {
$("<div />", {
"id" : "row" + i
}).appendTo("#parent");
for (var j = 0; j < input[i].length; j++) {
$("<div />", {
"class" : "child",
"id" : ("child" + i) + j
}).appendTo("#row" + i);
}
}
}
visualize();
main();
});
.child {
width: 25px;
height: 25px;
background-color: yellow;
border: 1px solid black;
margin: 1px;
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="parent"></div>
答案 1 :(得分:0)
你的问题是,当你去getValueAt
时,你传递的是数组长度,数组索引停在.length - 1
。参数是1太多了......如果你的“如果&#39;那么它就不会引发错误。声明是正确的:
// Add equal sign to last 2 conditions
if (x < 0 || y < 0 || x >= input.length || y >= input[x].length) {
return -1;
}
其他小事:
Floodfill
或FloodFill
; 答案 2 :(得分:0)
我正在查看你的getValueAt函数,边界条件不准确。数组元素从0索引到数组的长度减1,如果您尝试访问超出这些限制的元素,您将获得异常。尝试使用以下代码进入getValueAt函数的边界:
private static int getValueAt(int x, int y) {
if (x < 0 || y < 0 || x >= input.length || y >= input[x].length) {
return -1;
} else {
return input[x][y];
}
}
另外,我建议将初始apply更改为bounds,因为array.length或array [x] .length不在边界内。