Създаване на триъгълник с for Loops в Java

1. Въведение

В този урок ще проучим няколко начина за отпечатване на триъгълник в Java.

Естествено има много видове триъгълници. Тук ще изследваме само няколко от тях: правоъгълен и равнобедрен триъгълник.

2. Изграждане на правоъгълен триъгълник

Правоъгълният триъгълник е най-простият тип триъгълник, който ще изучаваме. Нека да разгледаме бързо резултата, който искаме да получим:

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

Тук забелязваме, че триъгълникът е направен от 5 реда, всеки от които има брой звезди, равен на номера на текущия ред. Разбира се, това наблюдение може да бъде обобщено: за всеки ред от 1 до N трябва да отпечатаме r звезди, където r е текущият ред, а N е общият брой редове.

И така, нека изградим триъгълника, като използваме две за цикли:

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. Изграждане на равнобедрен триъгълник

Сега, нека да разгледаме формата на равнобедрен триъгълник:

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

Какво виждаме в този случай? Забелязваме, че освен звездите, трябва да отпечатаме и някои интервали за всеки ред. И така, трябва да разберем колко интервали и звезди трябва да отпечатаме за всеки ред. Разбира се, броят на интервалите и звездите зависи от текущия ред.

Първо, виждаме, че трябва да отпечатаме 4 интервала за първия ред и, докато слизаме надолу по триъгълника, ни трябват 3 интервала, 2 интервала, 1 интервал и изобщо няма интервали за последния ред. Обобщавайки, трябва да отпечатаме N - r интервали за всеки ред .

Второ, сравнявайки с първия пример, осъзнаваме, че тук се нуждаем от нечетен брой звезди: 1, 3, 5, 7 ...

И така, трябва да отпечатаме rx 2 - 1 звезди за всеки ред .

3.1. Използване на Nested for Loops

Въз основа на горните наблюдения, нека създадем втория си пример:

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. Използване на един за цикъл

Всъщност имаме друг начин, който се състои само от един цикъл for - той използва библиотеката Apache Commons Lang 3.

Ще използваме цикъла 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(); }

Или можем да направим чист трик с метода substring () .

Можем да извлечем методите StringUtils.repeat () по-горе, за да изградим помощен низ и след това да приложим метода String.substring () върху него. Помощният низ е обединяване на максималния брой интервали и максималния брой звезди, от които се нуждаем, за да отпечатаме редовете на триъгълника.

Разглеждайки предишните примери, забелязваме, че се нуждаем от максимален брой N - 1 интервали за първия ред и максимален брой N x 2 - 1 звезди за последния ред:

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

Например, когато N = 5 и r = 3 , трябва да отпечатаме „*****“, което е включено в променливата helperString . Всичко, което трябва да направим, е да намерим правилната формула за метода substring () .

Сега нека видим пълния пример:

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(); }

По същия начин, само с малко повече работа, бихме могли да накараме триъгълника да се отпечата с главата надолу.

4. Сложност

Ако погледнем отново първия пример, забелязваме външен контур и вътрешен контур, всеки от които има максимум N стъпки. Следователно имаме O (N ^ 2) времева сложност, където N е броят на редовете на триъгълника.

Вторият пример е подобен - единствената разлика е, че имаме два вътрешни цикъла, които са последователни и не увеличават сложността на времето.

Третият пример обаче използва само цикъл for с N стъпки. Но на всяка стъпка извикваме или метода StringUtils.repeat () , или метода substring () в помощния низ, всеки от които има сложност O (N) . Така че цялостната времева сложност остава същата.

И накрая, ако говорим за спомагателното пространство, можем бързо да осъзнаем, че за всички примери сложността остава в променливата StringBuilder . Чрез добавяне на целия триъгълник към резултантната променлива, не можем да имаме по-малко от O (N ^ 2) сложност.

Разбира се, ако директно отпечатаме знаците, ще имаме постоянна сложност в пространството за първите два примера. Но третият пример използва помощния низ и сложността на пространството ще бъде O (N) .

5. Заключение

В този урок научихме как да отпечатваме два често срещани типа триъгълници в Java.

Първо, проучихме правоъгълния триъгълник, който е най-простият тип триъгълник, който можем да отпечатаме в Java. След това проучихме два начина за изграждане на равнобедрен триъгълник. Първият използва само за цикли, а другият се възползва от метода StringUtils.repeat () и String.substring () и ни помага да напишем по-малко код.

И накрая, ние анализирахме сложността във времето и пространството за всеки пример.

Както винаги, всички примери могат да бъдат намерени в GitHub.