Duvida: recursão

Estou tendo um problema com uma questão. O enunciado dela é esse:

Utilizando recursão, desenvolva um algoritmo para imprimir e calcular a soma dos “n” elementos de uma sequencia decrescente. Sendo “n” o valor informado pelo usuário.
Considere que a impressão deve apresentar um formato demonstrado no exemplo que segue.
Exemplo = se o valor informado pelo usuário for 93, o resultado impresso será:
Informe o elemento: 93

00093 00092 00091
00090 00089 00088 00087 00086 00085 00084 00083 00082 00081
00080 00079 00078 00077 00076 00075 00074 00073 00072 00071
00070 00069 00068 00067 00066 00065 00064 00063 00062 00061
00060 00059 00058 00057 00056 00055 00054 00053 00052 00051
00050 00049 00048 00047 00046 00045 00044 00043 00042 00041
00040 00039 00038 00037 00036 00035 00034 00033 00032 00031
00030 00029 00028 00027 00026 00025 00024 00023 00022 00021
00020 00019 00018 00017 00016 00015 00014 00013 00012 00011
00010 00009 00008 00007 00006 00005 00004 00003 00002 00001

A soma dos 93 elementos da sequencia é : 4371
Tempo: 3 milissegundos.

Consegui fazer a sequência em ordem decrescente, mas nao conseguir por pra somar.
Até então o meu codigo está assim:

package atividade23;
import java.util.Scanner;
public class Questão3 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		System.out.print("Digite um numero: ");
		int i = sc.nextInt(); 
		diminui(i);
	}
	
	private static void diminui(int i) {
		System.out.print(i + " ");
		System.out.println();
		int[] v = new int[i];
		int soma = 0;
		
		for (int j = 0; j < v.length; j++) {
			soma = v[j] + soma;
			System.out.print(v[j]);
		}
		
		if (i > 0)
			diminui(i - 1);
	}
}
1 curtida

É um termo usado de maneira mais geral para descrever o processo de repetição de um objeto de um jeito similar ao que já fora mostrado. Um bom exemplo disso são as imagens repetidas que aparecem quando dois espelhos são apontados um para o outro. (referencia: Recursividade)

public static void main(String[] args) {       
        
	Scanner sc = new Scanner(System.in);
	System.out.print("Digite um numero: ");
	int i = sc.nextInt(); 
	int soma = 0;
	diminui(i, soma);        
}

public static void diminui(int i, int soma)
{
	soma += i;
	System.out.printf("%0,5d\n", i);
	if (i > 1)
	{
		diminui((--i), soma);
	}
	else 
	{
		System.out.println("Soma total :" + soma);
	}
	
}

DEMO

Parabéns por pelo esforço, é muito importante tentar fazer os exercicios por si mesmo ao invés de apenas esperar a resposta pronta.

Testei seu código aqui e ele imprimiu coisas estranhas. Digitei o número 5 e a saída foi a seguinte:

Digite um numero: 5
5
000004
00003
0002
001
00

Quando deveria ser:

00005
00004
00003
00002
00001

Ou seja, deveria parar no 1 e depois mostrar a soma, que no caso seria 15, certo?

Tentei fazer umas modificações para ver se conseguia obter esta soma, mas não consegui e decidi fazer minha versão do método diminui e ficou assim:

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("Digite um numero: ");
        int i = sc.nextInt();
        System.out.println("Soma >>> " + diminui(i));
    }

    private static int diminui(int i) {
        /*
         * Primeiro você converte o valor de i para String.
         * Isso é necessário para sabermos quantos digitos tem o número armazenado nele.
         * De acordo com o enunciado, cada número deve ser impresso com 5 digitos.
         * Se o número for maior que 9999 não haveria problema pois 10000 já tem as cinco casas decimais.
         * O problema é que se i for um número com menos casas, precisamos de um jeito para preencher com zeros
         */
        String str = String.valueOf(i);

        /*
         * Aqui a gente testa pra ver se o tal número (agora convertido para String) tem os cinco digitos.
         * Se ele contiver menos de 5 digitos, vamos adicionando "0" ao seu inicio.
         * Se o valor for "1" ele só sairá do while quando for igual a "00001"
         * Se for "999", só sairá quando for "00999" e assim por diante. O número só sai quando tiver os 5 digitos.
         */
        while(str.length() < 5) {
            str = "0" + str;
        }

        /*
         * a variável soma é inicializada com o valor de i e não com 0
         */
        int soma = i;

        /*
         * O enunciado parece dizer para imprimirmos o valor de i, mas nós vamos imprimir a vesão
         * transformada em String de i
         */
        System.out.println(str);

        /*
         * A recursão deve parar no "00001" e é o que esse if nos assegura
         */
        if (i > 1)
            /*
             * O -- antes do i faz com que o valor de i seja diminuido em uma unidade e este valor é passado para o método diminui
             * Se o valor atual de i é 5, nós diminuimos para 4 e passado este novo valor para diminui e assim fazemos até que i seja igual ou menor que 1
             */
            soma += diminui(--i);

        /*
         * Terminamos retornando o resultado de soma
         */
        return soma;
    }
}

Comentei o máximo que pude para tentar deixar claro o porquê de cada trecho, espero que ajude.

O método diminui não consegue retornar a menos que o valor passado para ele seja igual ou menor que 1. Imagine que o invocamos passando o valor 5 como argumento.

diminui(5);

Quando chegar na linha:

soma += diminui(--i);

O que estará acontecendo por debaixo dos panos é isso:

soma += diminui(4);

Por sua vez diminui(4), internamente estará fazendo isso:

soma += diminui(3);

E assim segue até que i diminua até se tornar 1. Quando isso acontecer e o código chegar nesses trecho:

if ( i > 1 )

O resultado dará false e finalmente pulará para o return, que no caso seria 1. No final teriámos algo parecido com isso:

int soma = 5;

/* ... */

soma += diminui(4) + diminui(3) + diminui(2) + diminui(1);

kkk… Tentei explicar o efeito de recursão deste método e espero de todo coração não ter lhe atrapalhado mais ao invés de ajudar, é complicado até pra eu mesmo entender. De qualquer forma análise e tente tirar suas próprias conclusões, coloque printlns em todo lugar para ver o que ele imprime em determinadas partes do código.

1 curtida

kkk… Postamos quase ao mesmo tempo. Valeu!

1 curtida

Sim !!! mas, o que vale são a variedade de soluções e muito obrigado por ajuda a contribuir, vamos crescer cada vez mais!

1 curtida

Muito obrigada pelas respostas e explicações, me ajudou muito finalmente entendi onde estava errando, muito obrigada mesmo.

Ao invés de fazer aquele while para formatar o número, já há um método pronto pra isso.
String.format("%09d", numero);
Esse método formata seu numero botando zeros à esquerda, até fechar 9 algarismos. O código fica mais limpo e fácil de entender. Abraço

1 curtida