Obviamente hay que usar dos bucles anidados.
Para el primer triángulo, basta con que el bucle "interno" use como límite de su índice, el valor del índice del bucle "externo".
Así, según el bucle externo va aumentando su indice;1, 2, 3 , 4,... hasta llegar al valor de n, pues el bucle interno irá imprimiendo el valor de ese índice y lo hará tantas veces como indique el valor de dicho índice.
El segundo triángulo es muy parecido, pero hay diferencias importantes.
El bucle externo primero ha de ir aumentando su índice, o sea, incrementar.
Y cuando su índice llegue al valor n, ahora ha de cambiar y comenzar a decrementar para invertir el proceso que ha estado siguiendo.
Por tanto, el bucle externo no va a a poder establecer ningún incremento o decremento por sí mismo.
Para decidir si está en proceso de incrementación o de decrementación, tendremos que apoyarnos en un boolean. Mientras este sea TRUE, haremos que el índice se incremente.
Cuando el índice alcance el valor de n, cambiaremos el valor del boolean a FALSE y ahora el índice se decrementará hasta llegar a 0, que será la condición que pondrá fin al bucle externo.
Así explicado puede ser un poco confuso, quizás viendo el código escrito, se entienda mejor.
Fíjate que en el caso del segundo triángulo, su bucle for externo solo tiene dos argumentos, en lugar de los tres habituales.
No tiene el típico
i++ ni
i--. Estos argumentos son opcionales y hay casos como este, donde nos interesa omitir el argumento que indica cómo ha de variar el índice, ya que esta variación va a depender de lo que nos diga el boolean.
Estas son las soluciones que se me han ocurrido a mí, puede que haya otras distintas e incluso más eficientes.
Un saludo.