所以我试图在Java中创建一个Hosoya的三角形,并且我遇到了一些数学问题。我开始创建一个空的2D数组,其中有一个用户输入#of levels:
int[][] tri = new int[levels][];
//build the empty triangle
for (int row =0;row< tri.length;row++){
tri[row] = new int[row+1];
}
这部分功能齐全。我遇到的问题是在下一部分,我尝试用Fibonacci数字填充三角形(我添加了前面的代码块,因为我认为可能以不同的方式构建这个数组会有帮助) 。我尝试在循环之外创建前几个数字,然后将它们设置为1,然后开始实际循环tri[2][0]
,这是第3行。我已经在维基页面上看到了如何计算每个数字的方程式,但是当我尝试访问类似tri[0][1]
之类的东西时,我一直在抛出索引超出范围的错误。
for (int x=2;x<15;x++){ //TODO replace 15 with variable value
for (int y=0;y<15;y++){
tri[x][y] = tri[x-1][y] + tri[x-2][y];
}
15只是一个任意数字,因此它会为三角形中的每个数字循环。我已经测试了5个级别,因此有15个级别。我打算稍后解决这个问题。
我大多只是在绕着它的数学和三角形中每个数字之间的关系缠绕我的头。还有一个问题基本上是相同的here,但给出的答案对我来说并没有真正意义,而且它在3年内没有被触及,所以我在这里。
去年的另一个问题here从未得到回答,我想也许他们有正确的想法:也许我应该先构建三角形的左右两侧用不同的数学然后用一个单独的循环填充中间,总共3个。我真的不确定,我真的不知道下一步该去哪里。旁注:作业说我只需要递归地打印三角形,但如果用递归方法构建它将是我愿意听到任何想法的最佳方式。
递归和三角形本身的整个想法让我感到困惑,所以如果你真的彻底解释答案,我真的很感激,我有点努力赶上这堂课。 谢谢!
答案 0 :(得分:3)
首先,使用Hosoya三角形的Wiki页面上提供的格式更难看到数学。我们来看前5行:
1
1 1
2 1 2
3 2 2 3
5 3 4 3 5
并重新安排它们看起来像这样:
1
1 1
2 1 2
3 2 2 3
5 3 4 3 5
你现在可能会看到这种模式:
starting from the 3rd row:
for every number in the row
if the number has a number above it (i.e. all except the last number in each row)
it's the sum of the two numbers straight above it: H(n,j) = H(n-1,j) + H(n-2,j)
otherwise (i.e. the last number in each row)
it's the sum of the two numbers above it in the left diagonal: H(n,j) = H(n-1,j-1) + H(n-2),j-2)
重新格式化的数字可以存储在2D数组中,如图所示。然后我们需要做的就是用适当的空格打印出来,这样看起来就像Wiki页面上显示的那样:
public class HosoyaTriangle {
public static void main(String args[]) {
final int N = 10;
int[][] triangle = new int[N][N]; // this would initialize all cell elements to be 0
//populate the base cases for the first two rows
//H(0,0) = H(1,0) = H(1,1) = 1
triangle[0][0] = triangle[1][0] = triangle[1][1] = 1;
//starting from the 3rd row
for (int row = 2; row < N; row++) {
for (int col = 0; col < N; col++) {
if (col < row) {
//H(n,j) = H(n-1,j) + H(n-2,j)
triangle[row][col] = triangle[row - 1][col] + triangle[row - 2][col];
} else {
//H(n,j) = H(n-1,j-1) + H(n-2),j-2)
triangle[row][col] = triangle[row - 1][col - 1] + triangle[row - 2][col - 2];
}
}
}
print(triangle);
}
private static void print(int[][] matrix) {
final int level = matrix.length;
int spaceCount;
StringBuilder sb;
for (int row = 0; row < level; row++) {
sb = new StringBuilder();
//figure out how many spaces need to be printed before
//printing out the first non-zero number in the row
spaceCount = level - row - 1;
//add the spaces
while(spaceCount-- > 0) {
sb.append(" ");
}
//add all the non-zero numbers in the row
for (int col = 0; col < level; col++) {
if (matrix[row][col] > 0) {
sb.append(String.format("%4d",matrix[row][col]));
}
}
System.out.println(sb.toString());
}
}
}
输出:
1
1 1
2 1 2
3 2 2 3
5 3 4 3 5
8 5 6 6 5 8
13 8 10 9 10 8 13
21 13 16 15 15 16 13 21
34 21 26 24 25 24 26 21 34
55 34 42 39 40 40 39 42 34 55
编辑:
意识到你正在寻找递归解决方案。鉴于每个数字是由上面的行中的数字计算的,我们可以使用相同的fibonacci序列逻辑并从第N行开始,并递归向上传播util我们点击基本情况:
public static void main(String args[]) {
final int N = 10;
int[][] triangle = new int[N][N]; // this would initialize all cell elements to be 0
//only need to loop through the last row
//each column is calculated as a separate fibonacci sequence
for (int col = N - 1; col >= 0; col--) {
calc(N - 1, col, triangle);
}
print(triangle);
}
private static int calc(int row, int col, int[][] triangle) {
//base cases
if (row == 0 && col == 0 || row == 1 && col == 0 || row == 1 && col == 1 || row == 2 && col == 1) {
triangle[row][col] = 1;
} else {
if (col < row) {
//H(n,j) = H(n-1,j) + H(n-2,j)
triangle[row][col] = calc(row - 1, col, triangle) + calc(row - 2, col, triangle);
} else if (col == row) {
//H(n,j) = H(n-1,j-1) + H(n-2),j-2)
triangle[row][col] = calc(row - 1, col - 1, triangle) + calc(row - 2, col - 2, triangle);
}
}
return triangle[row][col];
}
请注意,此解决方案比非递归解决方案慢得多。