问题
So I'm trying to create a Hosoya's Triangle in Java, and I'm running into some math issues. I have started by making an empty 2D array that has a user input # 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];
}
this part is functional. The problem I'm having is in the next part, where I try to fill the triangle with Fibonacci numbers (I add the previous chunk of code because I'm thinking maybe building this array in a different way would help). I tried making the first few numbers outside the loop and just set them to 1, and then start actually looping at tri[2][0]
, which is the 3rd row. I've seen the equations on the wiki page of how to calculate each number, but I keep throwing index out of bounds errors when it tries to access something like 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];
}
the 15 is just an arbitrary number, so that it would loop for every number in the triangle. I've been testing with 5 levels so 15 works for that. I was planning to fix that later.
I'm mostly just having trouble wrapping my head around the math of it and the relationships between each number in the triangle. There is another question that's basically the same here but the answer given didn't really make sense to me, and it hasn't been touched in 3 years so here I am.
There's another question here from last year that never got answered, and I'm thinking maybe they have the right idea: maybe i should build the left and right sides of the triangle first with different math and then fill in the middle with a separate loop, making 3 in all. I'm really unsure though, and I don't really have a clue where to go next. Side note: the assignment says I only have to print the triangle recursively, but if building it with recursive methods would be the best way I'm willing to hear any ideas.
The whole idea of recursion and the triangle itself are kind of confusing to me so I would really appreciate if you explain answers really thoroughly, I'm kind of struggling to catch up in this class. Thanks!
回答1:
First of all, it's harder to see the math with the format provided on the Wiki page of Hosoya's triangle. Let's take the first 5 rows:
1
1 1
2 1 2
3 2 2 3
5 3 4 3 5
and re-arrange them to look like this:
1
1 1
2 1 2
3 2 2 3
5 3 4 3 5
and you could probably see the pattern now:
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)
The re-formatted numbers can be stored in a 2D array as shown. Then all we need to do is to print it out with proper spaces so it looks like the demonstration displayed on the Wiki page:
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());
}
}
}
Output:
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
EDIT:
Realized you're looking for a recursive solution. Given each number is calculated by the numbers in rows above, we can employ the same logic of fibonacci sequence and start from the Nth row, and recursively propagate upwards util we hit the base cases:
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];
}
Note that this solution is much slower than the non-recursive one.
来源:https://stackoverflow.com/questions/36275039/create-a-hosoyas-triangle-in-java