Creating a Triangle with for Loops in Java – 在Java中用for循环创建一个三角形

最后修改: 2019年 8月 19日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.绪论

In this tutorial, we’re going to explore several ways to print a triangle in Java.

在本教程中,我们将探讨在Java中打印一个三角形的几种方法。

There are, naturally, many types of triangles. Here, we’re going to explore only a couple of them: right and isosceles triangles.

自然,有许多类型的三角形。在这里,我们将只探讨其中的几个:直角三角形和等腰三角形。

2. Building a Right Triangle

2.建立一个直角三角形

The right triangle is the simplest type of triangle we’re going to study. Let’s have a quick look at the output we want to obtain:

直角三角形是我们要研究的最简单的三角形类型。让我们快速看一下我们想得到的输出。

*
**
***
****
*****

Here, we notice that the triangle is made of 5 rows, each having a number of stars equal to the current row number. Of course, this observation can be generalized: for each row from 1 to N, we have to print r stars, where r is the current row and N is the total number of rows.

在这里,我们注意到这个三角形是由5行组成的,每行的星星数量等于当前的行数。当然,这一观察可以被概括。从1到N的每一行,我们都要打印r星,其中r是当前行,N是行的总数。

So, let’s build the triangle using two for loops:

因此,让我们用两个for循环来构建三角形。

public static String printARightTriangle(int N) {
    StringBuilder result = new StringBuilder();
    for (int r = 1; r <= N; r++) {
        for (int j = 1; j <= r; j++) {
            result.append("*");
        }
        result.append(System.lineSeparator());
    }
    return result.toString();
}

3. Building an Isosceles Triangle

3.建立一个等腰三角形

Now, let’s take a look at the form of an isosceles triangle:

现在,让我们看一下等腰三角形的形式。

    *
   ***
  *****
 *******
*********

What do we see in this case? We notice that, in addition to the stars, we also need to print some spaces for each row. So, we have to figure it out how many spaces and stars we have to print for each row. Of course, the number of spaces and stars depends on the current row.

在这种情况下,我们看到了什么?我们注意到,除了星星之外,我们还需要为每一行打印一些空格。因此,我们必须弄清楚每一行要打印多少空格和星星。当然,空格和星星的数量取决于当前的行。

First, we see that we need to print 4 spaces for the first row and, as we get down the triangle, we need 3 spaces, 2 spaces, 1 space, and no spaces at all for the last row. Generalizing, we need to print N – r spaces for each row.

首先,我们看到第一行需要打印4个空格,随着三角形的深入,我们需要3个空格、2个空格、1个空格,最后一行则完全没有空格。一般来说,我们需要为每一行打印N – r个空格

Second, comparing with the first example, we realize that here we need an odd number of stars: 1, 3, 5, 7…

第二,与第一个例子相比较,我们意识到在这里我们需要奇数的星星:1,3,5,7……。

So, we need to print r x 2 – 1 stars for each row.

因此,我们需要为每一行打印r x 2 – 1

3.1. Using Nested for Loops

3.1.使用嵌套的for循环

Based on the above observations, let’s create our second example:

基于上述观察,让我们创建第二个例子。

public static String printAnIsoscelesTriangle(int N) {
    StringBuilder result = new StringBuilder();
    for (int r = 1; r <= N; r++) {
        for (int sp = 1; sp <= N - r; sp++) {
            result.append(" ");
        }
        for (int c = 1; c <= (r * 2) - 1; c++) {
            result.append("*");
        }
        result.append(System.lineSeparator());
    }
    return result.toString();
}

3.2. Using a Single for Loop

3.2.使用单个for循环

Actually, we have another way that consists only of a single for loop – it uses the Apache Commons Lang 3 library.

实际上,我们有另一种方法,只包括一个for循环–它使用Apache Commons Lang 3库

We’re going to use the for loop to iterate over the rows of the triangle as we did in the previous examples. Then, we’ll use the StringUtils.repeat() method in order to generate the necessary characters for each row:

我们将使用for循环来迭代三角形的行,就像我们在前面的例子中做的那样。然后,我们将使用StringUtils.repeat()方法,以便为每一行生成必要的字符。

public static String printAnIsoscelesTriangleUsingStringUtils(int N) {
    StringBuilder result = new StringBuilder();

    for (int r = 1; r <= N; r++) {
        result.append(StringUtils.repeat(' ', N - r));
        result.append(StringUtils.repeat('*', 2 * r - 1));
        result.append(System.lineSeparator());
    }
    return result.toString();
}

Or, we can do a neat trick with the substring() method.

或者,我们可以用substring()方法做一个巧妙的技巧。

We can extract the StringUtils.repeat() methods above to build a helper string and then apply the String.substring() method on it. The helper string is a concatenation of the maximum number of spaces and the maximum number of stars that we need to print the rows of the triangle.

我们可以提取上面的StringUtils.repeat()方法来建立一个辅助字符串,然后对其应用String.substring()方法。这个帮助字符串是我们需要打印三角形的行的最大空格数和最大星数的串联。

Looking at the previous examples, we notice that we need a maximum number of N – 1 spaces for the first row and a maximum number of N x 2 – 1 stars for the last row:

看看前面的例子,我们注意到,我们需要第一行的最大数量N – 1空间,以及最后一行的最大数量N x 2 – 1星。

String helperString = StringUtils.repeat(' ', N - 1) + StringUtils.repeat('*', N * 2 - 1);
// for N = 10, helperString = "    *********"

For instance, when N = 5 and r = 3, we need to print ”  *****”, which is included in the helperString variable. All we need to do is to find the right formula for the substring() method.

例如,当N = 5r = 3时,我们需要打印” *****”,它被包含在helperString变量中。我们需要做的就是为substring()方法找到正确的公式。

Now, let’s see the complete example:

现在,让我们看看完整的例子。

public static String printAnIsoscelesTriangleUsingSubstring(int N) {
    StringBuilder result = new StringBuilder();
    String helperString = StringUtils.repeat(' ', N - 1) + StringUtils.repeat('*', N * 2 - 1);

    for (int r = 0; r < N; r++) {
        result.append(helperString.substring(r, N + 2 * r));
        result.append(System.lineSeparator());
    }
    return result.toString();
}

Similarly, with just a bit more work, we could make the triangle print upside down.

同样地,只要多做一点工作,我们就可以让三角形倒过来印。

4. Complexity

4.复杂性

If we take a look again at the first example, we notice an outer loop and an inner loop each having a maximum of N steps. Therefore, we have O(N^2) time complexity, where N is the number of rows of the triangle.

如果我们再看一下第一个例子,我们注意到一个外循环和一个内循环,每个都有最大的N步。因此,我们有O(N^2)时间复杂性,其中N是三角形的行数。

The second example is similar — the only difference is that we have two inner loops, which are sequential and do not increase the time complexity.

第二个例子也是类似的–唯一的区别是我们有两个内循环,它们是连续的,不会增加时间的复杂性。

The third example, however, uses only a for loop with N steps. But, at every step, we’re calling either the StringUtils.repeat() method or the substring() method on the helper string, each having O(N) complexity. So, the overall time complexity remains the same.

然而,第三个例子只使用了一个for循环,有N步。但是,在每一步,我们都在调用StringUtils.repeat()方法或substring()方法,每个方法都有O(N)复杂性。所以,整体的时间复杂性保持不变。

Finally, if we’re talking about the auxiliary space, we can quickly realize that, for all examples, the complexity stays in the StringBuilder variable. By adding the entire triangle to the result variable, we cannot have less than O(N^2) complexity.

最后,如果我们谈论的是辅助空间,我们可以很快意识到,对于所有的例子,复杂性都停留在StringBuilder变量中。通过将整个三角形添加到result变量中,我们的复杂度不可能低于O(N^2)

Of course, if we directly printed the characters, we’d have constant space complexity for the first two examples. But, the third example uses the helper string and the space complexity would be O(N).

当然,如果我们直接打印字符,前两个例子的空间复杂度就会恒定。但是,第三个例子使用了辅助字符串,其空间复杂度将是O(N)

5. Conclusion

5.总结

In this tutorial, we’ve learned how to print two common types of triangles in Java.

在本教程中,我们已经学会了如何在Java中打印两种常见的三角形。

First, we’ve studied the right triangle, which is the simplest type of triangle we can print in Java. Then, we’ve explored two ways of building an isosceles triangle. The first one uses only for loops and the other one takes advantage of the StringUtils.repeat() and the String.substring() method and helps us write less code.

首先,我们研究了直角三角形,这是我们可以在Java中打印的最简单的三角形类型。然后,我们探讨了构建等腰三角形的两种方法。第一种方法只使用for循环,另一种方法利用了StringUtils.repeat()String.substring()方法,帮助我们写更少的代码。

Finally, we’ve analyzed the time and space complexity for each example.

最后,我们已经分析了每个例子的时间和空间复杂性。

As always, all the examples can be found over on GitHub.

一如既往,所有的例子都可以在GitHub上找到