[코드트리 조별과제] 4주차 (함수, 재귀함수)

·

17 min read

[코드트리 조별과제] 4주차 (함수, 재귀함수)

4주차 목표!

  • 저번주보다 더 많은 문제풀이 ✅

  • 손코딩으로 문제 풀어내는 부분에서는 규칙을 살펴보고 문제에서 무엇을 구하는지 알아내기 ✅

[문제풀이]

[함수] - 값을 반환하는 함수

  • a이상 b이하 수 중 소수이면서 모든 자릿수의 합이 짝수인 수의 개수
import java.util.Scanner;

public class Main {

        // 소수인지 구하기 
    public static boolean isPrime (int n) {
        if (n == 1) {
            return false;
        }

        for (int i = 2; i < n; i++) {
            if (n % i == 0) {
                return false;
            }
        }
        return true;
    }

        // 각 자리의 수의 합이 짝수
    public static boolean isEven (int n) {
        int sum = 0;
        while (n > 0) {
            sum += n % 10;
            n /= 10;
        }
        return sum % 2 == 0;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int a = sc.nextInt();
        int b = sc.nextInt();
        int cnt = 0;

        for (int i = a; i <= b; i++) {
            if (isPrime(i) && isEven(i)){  
                cnt++;
            }
        }
        System.out.print(cnt);  
    }
}
  • 소수구하기

    • 1은 소수가 아니다

    • 2 이상부터 n-1 까지 나누어 떨어지는 수가 없어야 한다. n % i != 0

[해설과 비교]

  • 반복문을 사용하지 않고 아래와 같이 간단히 풀어낸 점. → 입력 범위가 1 ~ 100까지였다.
int digitSum = (n / 100) + ((n / 10) % 10) + (n % 10);
  • 그리고 두개의 함수를 함수로 한번 더 처리하여 main에서 하나의 함수로만 조건문 판단에 넣었음.

  • 연속부분수열

// a 수열과 b수열의 첫번째값이 일치하는지 판단 후에
// 일치하지 않는다면 바로 return false를 통해 isSubsequence()함수로 넘어가고 다시 반복문 진행
// 그 다음 i++가 되므로 a수열의 다음 요소가 isSame(i)함수로 넘어간다.
// isSame(int n) 에서 반복문을 완료한다면 연속수열로 판단되어 return true;

public static boolean isSame(int n) {
        for(int i = 0; i < n2; i++)
            if(a[i + n] != b[i])
                return false;

        return true;
    }

    // ex) n1 수열이 6자리이고 n2 수열이 3자리이면
    // n1에서는 3자리까지만 n2의 첫번째 값이 일치하는지만 확인하면 된다.
    // 그래서 n1 - n2 의 조건식을 적용한 것.
    public static boolean isSubsequence() {
        for(int i = 0; i <= n1 - n2; i++)
            if(isSame(i))
                return true;

        return false;
    }
  • 날짜 존재 유무
// 월을 인자로 받아서 해당 월의 마지막 일자가 어디까지 있는 지 반환한다.
public static int lastDay(int m) {
        if(m == 2) {
            return 28;
        }

        if(m == 4 || m == 6 || m == 9 || m == 11) {
            return 30;
        }

        return 31;
    }

    // 월은 12 이하, 일은 해당 월의 마지막 월까지 조건범위
    public static boolean exist2021(int m, int d) {
        if(m <= 12 && d <= lastDay(m)) {
            return true;
        }

        return false;
    }
  • 계절 구하기
import java.util.Scanner;

public class Main {

    // 2월이면 윤년인지 판단.
    public static int lastDay(int y, int m) {
        if(m == 2) {
            if (y % 4 == 0 && y % 100 != 0 || y % 400 == 0) {
                return 29;
            } else {
                return 28;
            }
        }

        if(m == 4 || m == 6 || m == 9 || m == 11) {
            return 30;
        }
        return 31;
    }

        // 윤년에 따른 날짜 범위 판단.
    public static boolean existSeason(int y, int m, int d) {
        if(m <= 12 && d <= lastDay(y, m)) {
            return true;
        }    
        return false;
    }

    public static String season (int y, int m, int d) {
        String result = "";
        if (existSeason(y, m, d)) {  // 해당연도에 날짜가 존재한다면
            switch (m) {
            case 3: case 4: case 5: result = "Spring"; break;
            case 6: case 7: case 8: result ="Summer"; break;
            case 9: case 10: case 11: result ="Fall"; break;
            case 12: case 1: case 2: result ="Winter"; 
            }
            return result;
        }
        return "-1";
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int year = sc.nextInt();
        int month = sc.nextInt();
        int day = sc.nextInt();

        System.out.print(season(year, month, day));
    }
}

[함수] - Call by value / Call by reference

  • Call By Value : Java에서는 함수에 인자를 넘길 때 기본적으로 값을 복사해서 넘겨주게 된다.

    • Primitive type(원시 타입)

      • int, long, double, float, boolean, byte, short, char

      • 스택(stack) 메모리 에 저장된다.

    • Reference Type(참조 타입)

      • 원시 타입을 제외한 나머지 타입들 (문자열, 배열, 열거, 클래스, 인터페이스)

      • 실제 객체는 힙(heap) 메모리에 저장

      • 참조 타입 변수는 스택(stack) 메모리 에 실제 객체들의 주소를 저장

      • 객체(값)는 Heap 영역에 저장되고, Stack 영역에 있는 변수가 객체의 주소값을 갖고 있다.

  • 두 정수 값 교환하기
import java.util.Scanner;

class IntWrapper {
    int value;

    public IntWrapper(int value) {
        this.value = value;
    }
}

public class Main {

    public static void swap (IntWrapper n, IntWrapper m) {
        int temp = n.value;
        n.value = m.value;
        m.value = temp;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();
        int m = sc.nextInt();

        IntWrapper nWrap = new IntWrapper(n);  // 객체 생성
        IntWrapper mWrap = new IntWrapper(m);  // 객체 생성

        swap(nWrap, mWrap); //객체 주소 
        System.out.print(nWrap.value + " " + mWrap.value);
    }
}
  • 리스트를 인자로 받는 함수

    • 배열은 reference type

    • Stack에 정의된 arr2 변수가 Heap에 정의된 arr 배열의 값을 가리키고 있기에 그 값을 수정했을 때 직접 영향을 미치게 된다.

    • 배열의 값을 복사해서 사용하고 싶으면 .clone()을 사용하자. 기존 배열과 동일한 원소를 갖는 새로운 배열을 만들어 넘겨주게 되므로, 함수 안에서의 변화가 함수 밖의 변수에 영향을 끼치지 않게 된다.

public class Main {
    public static void modify(int[] arr2) {  // arr2는 arr와 관련이 없다.
        arr2[0] = 10;
    }

    public static void main(String[] args) {
        int[] arr = new int[]{1, 2, 3, 4};
        modify(arr.clone());                 // 새로운 배열을 만들어 넘기기

        for(int i = 0; i < 4; i++)
            System.out.print(arr[i] + " ");
    }
}

>> 1 2 3 4 # 값에 변화가 없다
  • 배열 요소 중 짝수만 2로 나누기
import java.util.Scanner;

public class Main {

    public static void evenDivide(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] % 2 == 0) {
                arr[i] /= 2;
            }
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();
        int [] arr = new int[n];

        for (int i = 0; i < n; i++) {
            arr[i] = sc.nextInt();
        }

        evenDivide(arr);  // 배열의 주소

        for (int num : arr) {
            System.out.print(num + " ");
        }
    }
}
  • String

    • String은 immutable하다! →. immutable하다는 것은 값을 바꿀 수 없는 type이라는 뜻

    • 동시에 String은 reference type

public class Main {
    public static void modify(String s) {
        s += "apple";  // 새로운 문자열을 만든 뒤에 s에 대입
    }

    public static void main(String[] args) {
        String str = "banana";
        modify(str);  // str에는 영향이 없다.
        System.out.print(str);  
    }
}
>> banana
public class Main {
    public static String modify(String s) {
        s += "apple";
        return s;  // 새로운 문자열을 retrun
    }

    public static void main(String[] args) {
        String str = "banana";
        str = modify(str);
        System.out.print(str);
    }
}

>> bananaapple
  • palindrome : 문자열을 뒤집었을 때도 동일한 문자열인 경우
import java.util.Scanner;

public class Main {

    public static boolean palindrome (String str) {
        String reverseStr = "";
        for (int i = str.length()-1; i >= 0; i--) {
            reverseStr += str.charAt(i);
        }

        if (str.equals(reverseStr)) {
            return true;
        }
        return false;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        String str = sc.next();

        if (palindrome(str)) {
            System.out.print("Yes");
        } else {
            System.out.print("No");
        }
    }
}

[해설과 비교]

문자열의 0자리 ↔ str.length() -1 -i 를 하나씩 비교

나는 그냥 다 뒤집은 문자를 하나 만들어서 equals로 비교함. 밑에 코드보다 효율성이 떨어짐

왜냐하면 밑의 코드는 중간에 비교하다가 아니면 바로 return false를 하기 때문에 문자를 다 뒤집는 반복문이 다 실행되지 않아도 반복 및 함수가 종료되고 반환된다.

public static boolean palindrome(String s) {
        for(int i = 0; i < s.length(); i++)
            if(s.charAt(i) != s.charAt(s.length() - i - 1))
                return false;

        return true;
    }
  • 객체 만든 후에 두 정의 연산값 구하기
import java.util.Scanner;

class AbStation {
    int aValue;
    int bValue;

    public AbStation(int a, int b) {
        this.aValue = a;
        this.bValue = b;
    }
}

public class Main {

    public static void calculate(AbStation ab) {
        if (ab.aValue > ab.bValue) {
            ab.aValue += 25;
            ab.bValue *= 2;
        } else {
            ab.aValue *= 2;;
            ab.bValue += 25;;
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int a = sc.nextInt();
        int b = sc.nextInt();

        AbStation ab = new AbStation(a, b);

        calculate(ab);

        System.out.print(ab.aValue + " " + ab.bValue);
    }
}
  • 해설에서는 a와 b에 새로운 객체를 생성해서 값을 변경했지만 나는 한 클래스에 a와 b의 값을 넣어두고 한번에 처리해봤다.

  • 배열 요소 절댓값으로 변경

import java.util.Scanner;

public class Main {

    public static void absNum (int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] < 0) {
                arr[i] *= -1;
            }
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();
        int[] arr = new int[n];

        for (int i = 0; i < n; i++) {
            arr[i] = sc.nextInt();
        }

        absNum(arr);

        for (int num : arr) {
            System.out.print(num + " ");
        }
    }
}
  • 문자열 A에 서로 다른 알파벳의 수가 2개 이상
import java.util.Scanner;

public class Main {

    public static boolean twiceAlphabet(String str) {
        int cnt = 1;
        for (int i = 0; i < str.length(); i++) {
            if (str.charAt(0) != str.charAt(i)) {
                cnt++;
            }

            if (cnt == 2) {
                return true;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        String str = sc.next();

        if (twiceAlphabet(str)) {
            System.out.print("Yes");
        } else {
            System.out.print("No");
        }
    }
}

[해설과 비교]

나는 cnt를 사용했는데 그럴필요가 없었다 이미 문자열의 첫번째 자리와 다른 자리가 다르다면 이미 서로 다른 알파벳이 2개가 되기 때문에 바로 return을 하면 된다. 개수 따지지 않고

// 하나라도 서로 다른 알파벳이 있다면 알파벳이 2개 이상
    int len = str.length();
    for(int i = 0; i < len; i++)
        if(str.charAt(i) != str.charAt(0))
            return true;

    return false;
  • 앞에서 똑같이 연산을 하는 함수 앞에서는 똑같은 문제여서 한 객체에 a, b 두개의 값을 모두 보내서 해결하였고 이번에는 a와 b를 각각 인자로 보내서 처리하였다.
import java.util.Scanner;

class AbStation {
    int value;

    public AbStation(int val) {
        this.value = val;
    }
}

public class Main {

    public static void calculate(AbStation a, AbStation b) {
        if (a.value > b.value) {
            a.value *= 2;
            b.value += 10;
        } else {
            a.value += 10;
            b.value *= 2;
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int a = sc.nextInt();
        int b = sc.nextInt();

        AbStation aValue = new AbStation(a);
        AbStation bValue = new AbStation(b);

        calculate(aValue, bValue);

        a = aValue.value;
        b = bValue.value;

        System.out.print(a + " " + b);

    }
}

[함수] - 변수의 영역

  • 전역번수 사용하기
import java.util.Scanner;

public class Main {
    public static String input;
    public static String goal;

    public static int existPart() {
        int inLen = input.length();
        int goLen = goal.length();
        for (int i = 0; i <= inLen - goLen; i++) {
            int cnt = 0;
            for (int j = 0; j < goLen; j++) {
                if (input.charAt(i+j) == goal.charAt(j)) {
                    cnt++;
                }

                if (cnt == goLen) {
                    return i;
                }
            }    
        }

        return -1;  
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        input = sc.next();
        goal = sc.next();

        int result = existPart();     
        System.out.print(result);
    }
}

[해설과 비교]

// 부분 문자열이 될 수 있는지 먼저 판단
public static boolean isSubStr(int startIdx) {
    int n = text.length();
    int m = pattern.length();

    if(startIdx + m - 1 >= n) // 패턴 문자열이 원본 문자열 범위를 초과하는지
        return false;

    // 넘겨온 인덱스에서부터 패턴 길이만큼 비교한다.
    // 카운트를 쓰지않고 중간에 하나라도 다르면 return false하도록한다.
        for(int j = 0; j < m; j++) {
            if(text.charAt(startIdx + j) != pattern.charAt(j))
                return false;
        }

        // 전부 일치
        return true;
    }

    // 부분 문자열의 위치 반환
    public static int findIndex() {
        int n = text.length();
        for(int i = 0; i < n; i++) {
            // 부분 문자열이면 해당 인덱스 반환 
            if(isSubStr(i))
                return i;
        }

        // 없다면 -1 반환 
        return -1;
    }
  • 변수의 범위 scope

    • 함수 안에서 정의한 변수는 함수 안에서만 사용가능 → 이러한 변수를 local 변수(지역변수)

    • 함수 안에서 정의된 변수의 경우에는 함수가 종료되는 순간에 변수도 같이 사라진다.

    • for문 안에서도 마찬가지로 동작한다.

public class Main {
    public static int a = 10, b = 20;

    public static void printAandB() {
        System.out.println(a + " " + b); // 10 20
    }

    public static void modify(int a, int b) {
        System.out.println(a + " " + b);  // 50 60
        printAandB();  // 10 20
        int temp = a;
        a = b;
        b = temp;
    }

    public static void main(String[] args) {
        modify(50, 60);
        printAandB();
    }
}

위의 코드에서 처럼 같은 변수 이름을 갖는 경우는 가장 가까이에 있는 변수를 사용하게 된다.

  • 나누고 빼면서 합하기
import java.util.Scanner;

public class Main {

    public static int m;

    public static int sumArr(int[] arr) {
        int sum = 0;
        while (m > 0) {
            sum += arr[m-1];

            if (m % 2 == 0) { 
                m /= 2;
            } else {
                m--;
            }
        }
        return sum;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
       int n = sc.nextInt();
       m = sc.nextInt();

       int [] arr = new int[n];

       for (int i = 0; i < n; i++) {
        arr[i] = sc.nextInt();
       }

       int result = sumArr(arr);
       System.out.print(result);
    }
}
  • 특정 구간 합
import java.util.Scanner;

public class Main {

    public static int [] arr = new int[101];

    public static void sumAll(int[][] pair) {
        for (int i = 0; i < pair.length; i++) {
            int sum = 0;

            for (int j = pair[i][0]; j <= pair[i][1]; j++) {
                    sum += arr[j];
                }
                System.out.println(sum);
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();
        int m = sc.nextInt();
        int [][] pair = new int[m][2];

        for (int i = 1; i <= n; i++) {
            arr[i] = sc.nextInt();
        }

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < 2; j++) {
                pair[i][j] = sc.nextInt();
            }
        }
        sumAll(pair);
    }
}

[해설과 비교]

풀고나니 엄청 쉬웠던 문제 나는 왜 2차원배열까지 쓴거지?

for(int i = 1; i <= m; i++) {
    int a1 = sc.nextInt();
    int a2 = sc.nextInt();
    System.out.println(getAnswer(a1, a2));  // 입력받는대로 함수호출했다. 
}

[재귀함수] - 값을 반환하지 않는 재귀함수

  • 정의된 함수 f가 해당 함수를 구현하는 데 동일한 함수 f를 다시 이용하게 되는 것을 재귀함수

  • 재귀함수에서 가장 중요한 요소는 바로 종료 조건이다.

public class Main {
    public static void printStar(int n) { 
        if(n == 0)                        // n이 1이라면 return -> 자신을 호출한 곳으로
            return;                     

        printStar(n - 1);                 // n-1 을 인자로 사용하는 재귀함수
        System.out.println("*****");      
    }

    public static void main(String[] args) {
        System.out.println("start");
        printStar(3);
        System.out.println("end");
    }
}
  • 함수 호출 시 어디로 가는지 꼭 확인 필수.
import java.util.Scanner;

public class Main {

    public static void printHello(int n) {
        if (n == 0) {     // n이 0이된다면 retrun
            return;
        }

        printHello(n-1);   // 자신을 호출함 
        System.out.println("HelloWorld"); // 0 → return → 1 → 2 → n까지 순서대로 
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();

        printHello(n);
    }
}
  • 재귀함수의 위치에 따라 달라지는 출력결과
public static void printStar(int n) { 
    if(n == 0)                        
        return;

    printStar(n - 1);                 // 자신 호출 
    for(int i = 0; i < n; i++)        // 출력
        System.out.print("*");
    System.out.println();
}

printStar(3);   // 0 return > 1 > 2 > 3
>> *
   **
   ***
public static void printStar(int n) { 
    if(n == 0)                        
        return;

    for(int i = 0; i < n; i++)        // 출력
        System.out.print("*");
    System.out.println();
    printStar(n - 1);               // 자신 호출  
}

printStar(3);  // 3 > 2 > 1  0 return 
>> ***
   **
   *
public static void printStar(int n) {
    if(n == 0)
        return;

    for(int i = 0; i < n; i++)    // 출력
        System.out.print("*");
    System.out.println();
    printStar(n - 1);             // 자신 호출
    for(int i = 0; i < n; i++)    // 출력
        System.out.print("*");
    System.out.println();
}

printStar(3); // 3 > 2 > 1 > 0 return > 1 > 2 > 3 

>> ***
   **
   *
   *
   **
   ***
  • 숫자 차례로 출력하기
import java.util.Scanner;

public class Main {

    public static void printOrder (int n) {
        if (n == 0) {
            return;
        }

        printOrder(n-1);
        System.out.print(n + " ");

    }

    public static void printReverse (int n) {
        if (n == 0) {
            return;
        }

        System.out.print(n + " ");
        printReverse(n-1);

    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();

        printOrder(n);
        System.out.println();
        printReverse(n);
    }
}
  • 재귀함수를 이용한 별출력
import java.util.Scanner;

public class Main {

    public static void printStar (int n) {
        if (n == 0) {
            return;
        }

        printStar(n-1);
        for (int i = 0; i < n; i++) {
            System.out.print("*");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();

        printStar(n);
    }
}
  • 재귀함수의 꽃
import java.util.Scanner;

public class Main {

    public static void printNumber (int n) {
        if (n == 0) {
            return;
        }

        System.out.print(n + " ");
        printNumber(n-1);
        System.out.print(n + " ");
    }
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();

        printNumber(n);
    }
}
  • 재귀함수를 이용한 별출력
import java.util.Scanner;

public class Main {

    public static void printStar (int n) {
        if (n == 0) {
            return;
        }

        for (int i = 0; i < n; i++) {
            System.out.print("* ");
        }
        System.out.println();

        printStar(n-1);

        for (int i = 0; i < n; i++) {
            System.out.print("* ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
       Scanner sc = new Scanner(System.in);

       int n = sc.nextInt();

       printStar(n);
    }
}

[재귀함수] - 값을 반환하는 재귀함수

  • 재귀함수는 종료조건이 없으면 계속 함수 호출을 반복한다.

  • 값을 반환하는 재귀함수에서의 종료조건 → 계산 없이도 바로 결과를 알 수 있는 경우 로 설정하는 것이 대부분이다.

이 식에서 1! 즉 fact(1)이 1이라는 것을 당연하게 알고 있으므로, 이 조건을 종료조건으로 걸어 이 문제를 해결할 수 있다.

public class Main {
    public static int fact(int n) {
        if(n == 1)
            return 1;

        return fact(n - 1) * n;
    }
    public static void main(String[] args) {
        System.out.println(fact(3));
    }
}

>> 6
  • 1부터 n까지의 합
import java.util.Scanner;

public class Main {

    public static int sumAll (int n) {
        if (n == 1) {   // 종료조건 
            return 1;
        }
        return sumAll(n-1) + n;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();

        System.out.print(sumAll(n));
    }
}
  • 각 자리 숫자의 합
public class Main {
    public static int F(int n) {
        if(n < 10)   // 1의 자리가 되는 것이 종료조건
            return n;

        return F(n / 10) + (n % 10);
    }
    public static void main(String[] args) {
        System.out.println(F(1527));
    }
}

>> 15
  • 각 자리 숫자의 제곱
import java.util.Scanner;

public class Main {

    public static int powerSum (int n) {
        if (n < 10) {
            return n * n;  // 마지막 한자리가 남았을때 제곱을 해서 보낸다.
        }

        return powerSum(n/10) + (n % 10) * (n % 10); // 그 다음부터는 끝자리 제곱의 합
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();

        System.out.print(powerSum(n));
    }
}
  • 1이 되기까지 횟수
import java.util.Scanner;

public class Main {

    public static int countNum (int n) {

        if (n == 1) {   // 1이 된다면 0 return
            return 0;
        }

        if (n % 2 == 0) {  // 짝수일 때
            n /= 2;
        } else {           // 홀수일 때 
            n /= 3;
        }
        return countNum(n) + 1;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();

        System.out.print(countNum(n));
    }
}

  • 점화식과 수열의 n번째 원소

    • A1 = 2, A2 = 7, 그리고 An = An-1 + 2 * An-2 를 만족하는 수열이 있을 때 n번째 원소의 값을 구해보자.

    • 점화식 → 재귀함수에서 어떤 함수를 호출해야 하는지에 대한 힌트

    • A1, A2와 같은 초기값들 → 종료 조건에 대한 정보

// F(n)을 n번째 원소를 구하는 함수라고 했을 때의 코드
public class Main {
    public static int F(int n) {
        // 종료 조건
        if(n == 1)
            return 2;
        if(n == 2)
            return 7;

        // 점화식
        return F(n - 1) + 2 * F(n - 2);  // 2개의 재귀함수
    }
    public static void main(String[] args) {
        System.out.println(F(4));
    }
}

>> 25
  • 재귀함수를 이용한 피보나치 수
import java.util.Scanner;

public class Main {

    public static int fibonacci (int n) {
        if (n == 1 || n == 2) {
            return 1;
        }
        return fibonacci(n-2) + fibonacci(n-1);
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();

        System.out.print(fibonacci(n)); 
    }
}
  • 재귀트리 그려서 값 구하기

https://contents.codetree.ai/problems/696/images/f0301249-bc95-427b-b156-25f448f37085.png

(그림 출처 : 코드트리)

  • 그림을 그려서 규칙을 찾아내니까 더 쉬움.

  • factorial

import java.util.Scanner;

public class Main {

    public static int factorial (int n) {
        if (n == 0) {
            return 1;
        }

        return n * factorial(n-1);
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();

        System.out.print(factorial(n));
    }
}
  • 홀수 짝수에 따른 출력값
import java.util.Scanner;

public class Main {

    public static int sumAll (int n) {
        if (n == 2) { // 그대신 짝수는 2가 되면 2를 return해야하고
            return 2;
        }

        if (n == 1) { // 홀수는 1이 되면 1을 return 해야함. 
            return 1;
        }
        return n + sumAll(n-2); // 홀수와 짝수 모두 2씩 차이
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();

        System.out.print(sumAll(n));
    }
}
  • 재귀함수를 이용한 최댓값
import java.util.Scanner;

public class Main {
    public static final int MAX_N = 100;

    public static int[] arr = new int[MAX_N];

    public static int maxNum(int n) {
       if(n == 0)
            return arr[0];

        return Math.max(maxNum(n - 1), arr[n]);
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();

        for (int i = 0; i < n; i++) {
            arr[i] = sc.nextInt();
        }

        System.out.print(maxNum(n - 1));

    }
}
  • 큰 숫자 자리수의 합
import java.util.Scanner;

public class Main {

    public static int sumAll(int n) {
        if (n < 10) {
            return n;
        }

        return sumAll(n/10) + (n%10);
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int num = 1;
        for (int i = 0; i < 3; i++) {
            num *= sc.nextInt();
        }

        System.out.print(sumAll(num));
    }
}