본문 바로가기
Today I Learned 2024. 4. 26.

(24.04.26)[2주차] 알고리즘 심화 세션 정리, 과제 이슈 정리

과제 코드가 처음하는 사람에게 복잡하기도 해서 걱정이 너무 막막하다

캠프쪽은 이렇게 쉬운 과제인데 왜 아직도 제출을 안하냐는 입장이라 괜히 억울한 입장

그래도 차근히 풀고있다.


알고리즘 심화 세션 정리

  • 시간 복잡도를 좀더 쉽게 풀어서 복습 겸 강의 내용과 합쳐서 정리
더보기

알고리즘 심화

의사코드 Pseudo-code

  • 알고리즘 또는 프로그램이 수행할 내용을 논리적 서술한 것
  • 코드와 비슷하지만 인간의 언어로 흉내내서 적어놓는것
// 1차월 배열 x를 입력으로 받는다
maxScore(x[])
{
	// 최댓값 max를 0으로 초기화
	max <- 0;
	
	// 배열의 요소 갯수만큼 반복한다
	for (i <- 0; i < x.length; i <- i+1) do {
		// 해당 배열의 요소 값이 최댓값보다 크거나 같다면
		if (x[i] >= max) then {
			// 해당 값을 최댓값으로 지정한다
			max <- x[i];
		}
	}
	
	return max;
}

알고리즘 평가

ex) for 문자

  • 위의 for문이 반복하면서 하나하나 최댓값을 구하는 알고리즘이기 때문에 걸리는 시간은 바깥 for문의 소요 시간 * n
    • 내부 for가 있을 경우 시간은 n*n 으로 늘어나게 됨

시간 복잡도 Time complexity

  • 작성된 알고리즘이 효율적으로 빠르게 문제를 해결했는지 평가를 할 수 있는 지표

Big-O 표기법

  • 알고리즘 입력 크기가 n일경우, 그에 해당하는 최악의 상황의 시간을 표기하는 법
  • Big-O 표기법의 복잡도 비교
  • O(1) < O( 𝑙𝑜𝑔𝑛 ) < O(n) < O(n 𝑙𝑜𝑔𝑛 ) < O( 𝑛2 ) < O( 2𝑛 ) < O(n!)

 

CODE KATA 이슈 정리

더보기
import java.util.Collections;
import java.util.Arrays;
import java.util.ArrayList;

class Solution {
    public int[] solution(long n) {
        String str = String.valueOf(n);
        char[] chr = str.toCharArray();
        
        ArrayList<Integer> intList = new ArrayList<>();
        
        for(char c : chr) {
            int i = c - '0';
            intList.add(i);
        }
       
        Collections.reverse(intList); // 거꾸로 정렬
        
        int[] answer = new int[chr.length];
        for(int i = 0; i<chr.length; i++){
            answer[i]=intList.get(i);
        }
        
        return answer;
    }
}

char 타입을 int 타입으로 변환 이슈

이슈

  • 계속 char -> int 타입으로 바꿔서 인덱스로 넣은 값이 두자릿수 정수로 바뀌어서 입력 및 출력

원인

  • Java에서는  char 타입과 int 타입이 서로 자유롭게 형변환되어 바꿔쓸 수 있다고 알고 있었기에 형변환을  int i =(char)c 식으로 진행
    • Java에서는 서로 자유롭게 바꿀 수 있으나 단 ASCII 코드로 변환을 해서 바꿔지고 ASCII 에서도 정수는 다른 코드 값을 가지고 있기 때문에 ASCII 코드 값으로 변환을 시켰던 것

해결

  • 가장 쉬운 방법으로  ASCII 값 기준 정수 0 변환할 정수까지의 구간 = 변환할 정수 이므로 그냥  int i = c - '0' 해주면 끝
    • 0역시 char 타입이어야하므로 '0'으로 써줘야
  • 새롭게 찾은 방법 : Wrapper 클래스 Character  클래스의 getNumericValue 메서드를 사용
    • int i = Character.getNumericValue(c); 해주기만 하면 됨
    • 그런데 그냥 - '0' 만 쓰는 위의 방법만 해주면 가능하므로 명확하게 변환해야하지 않는 이상 거의 사용X

 

과제 이슈 정리

더보기
package calculator;

import java.util.*;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;

public class App {
    public static void main(String[] args) throws DivideException {

        Scanner sc = new Scanner(System.in);
        /* exit 문자열이 입력될 때 까지 연산 반복 반복문*/
        String input = null; // do - while 반복문 조건에 넣기 위해 입력값 초기화
        do {
            System.out.print("첫 번째 숫자를 입력하세요: ");
            /* Scanner를 사용하여 양의 정수를 입력받고 적합한 타입의 변수에 저장합니다. */
            int num1 = sc.nextInt();
            System.out.print("사칙연산 기호를 입력하세요: "); // + - * / 중 하나를 입력받음
            /* charAt(idx)는 String타입 하나 입력된 기호를 charAt으로 char타입의 변수로 선언 */
            char operator = sc.next().charAt(0);
            System.out.print("두 번째 숫자를 입력하세요: ");
            /* Scanner를 사용하여 양의 정수를 입력받고 적합한 타입의 변수에 저장합니다. */
            int num2 = sc.nextInt();


            /*Calculator의 DivideException Handling*/
            try {
                /*Calculator 클래스를 활용한 사칙연산*/
                Deque<Double> calculationResult = Calculator.calculate(num1, num2, operator);
                /*최근 연산값 출력*/
                System.out.println("결과: " + calculationResult.peekLast());
            } catch (DivideException e1) {
                System.out.println(e1.getMessage());
            }



            /*remove입력시 calculationResult 최초 연산 삭제*/
            System.out.println("가장 먼저 저장된 연산 결과를 삭제하시겠습니까? (remove 입력 시 삭제)");
            input = sc.next();
            if (input.equals("remove")) {
                Calculator.calculationResult.pollFirst(); // 가장 처음값 꺼내서 없애기
            }


            /*inquiry입력시 calculationResult 전부 출력*/
            System.out.println("저장된 연산결과를 조회하시겠습니까? (inquiry 입력 시 조회)");
            input = sc.next();
            if (input.equals("inquiry")) {
                for (double resultIndex : Calculator.calculationResult) {
                    System.out.println(resultIndex); // 한 줄씩 출력
                }
            }


            /*추가 연산 여부 확인*/
            System.out.println("더 계산하시겠습니까? (exit 입력 시 종료)");
            input = sc.next();

        } while (!(input.equals("exit"))); // exit이 입력되면 반복문 종료, 그 외에는 계속 반복와


    }
}

public class Calculator {
    /* 연산 결과를 저장하는 Deque 선언 및 생성 */
    static Deque<Double> calculationResult = new LinkedList<>();

    public static Deque<Double> calculate(int num1, int num2, char operator) throws DivideException {
        double result = 0;

        /*사칙연산 & 나눗셈오류출력*/
        if (operator == '/' && num2 == 0) { // 분모가 0인 나눗셈은 연산 없이 경고문구 출력
            /**/
            throw new DivideException("나눗셈 연산에서 분모에 0이 입력될 수 없습니다.");
        } else {
            /* 입력된 operator 값 + - * / 에 따라 각각 연산 후, 결과값 출력*/
            switch (operator) {
                case '+':
                    result = num1 + num2;
                    break;
                case '-':
                    result = num1 - num2;
                    break;
                case '*':
                    result = num1 * num2;
                    break;
                case '/':
                    result = (double)num1 / num2;
                    break;
            }
            calculationResult.add(result);
            return calculationResult;
        }
    }
}

class DivideException extends Exception {
    public DivideException(String input) {
        super(input);
    }
}

calculationResult 변수 Cannot resolve symbol 에러

이슈

  • 연산 값이 저장되는 calculationResult 변수를 정확히 무슨 symbol인지 인지를 못하는 상황

원인

  • 이미 작성한 App 클래스 문에서 있었던 calculationResult  변수가 Calculation 클래스를 활용 try-catch 문의 블락으로 들어가버림
    • 따라서, Calculation 클래스 내부의 Deque인  calculationResult에 저장되는 형태
    • 또 로컬 변수에 대해선 인지를 잘 못했기 때문에 헤맸던 것

해결

  • Calculation클래스의 calculationResult를 불러와야하므로 Calculation.calculationResult 으로 변경

 

 


 

간단한 내용만 수정해도 10시간이 넘게 하루종일 매달렸다.

스트레스가 너무 받기도하고, 처음하는 사람에게 너무 많은 것을 과제로 내준 것 같아서

오히려 짜증이 날 지경

그래도 어쩔수 없이 해야할 것

 

-