프로그래머스 시저 암호 제일 작은 수 제거하기 (99클럽 코딩테스트 19일차 TIL)

KIMYEONGJUN·2024년 4월 15일
0
post-thumbnail

목표

문제들을 통해서 문자열 알고리즘을 공부하고있는데 아직 문제가 익숙지 않아서 어려움이 있다. 하지만 비슷한 문제를 풀어보면서 알고리즘 공부에 익숙히 지기위해서 공부하는게 내 목표이다.

문제

내가 생각했을때 문제에서 원하는부분

어떤 문장의 각 알파벳을 일정한 거리만큼 밀어서 다른 알파벳으로 바꾸는 암호화 방식을 시저 암호라고 한다.
예를 들어 "AB"는 1만큼 밀면 "BC"가 되고, 3만큼 밀면 "DE"가 됩니다. "z"는 1만큼 밀면 "a"가 된다. 
문자열 s와 거리 n을 입력받아 s를 n만큼 민 암호문을 만드는 함수

내가 이 문제를 보고 생각해본 부분

문자열을 char 배열로 변환한 이유
Java의 String 클래스는 immutable(불변)한 성질을 가진다.
문자열을 직접 변경할 수 없고, 새로운 문자열을 생성해야 한다.
이는 불필요한 객체 생성과 메모리 낭비를 하게된다.
반면 char 배열은 수정이 가능하다.
따라서 문자열을 직접 순회하면서 변경하기 위해 char 배열을 사용한 것이다.
아스키 코드를 활용한 이유
아스키 코드는 알파벳과 정수 코드가 1:1 대응되어 있다.
A = 65, B = 66 식으로 매핑되어 있어서 코드 수치 상 변환이 용이하다.
알파벳의 순번과 아스키 코드 값의 관계를 이용하여 시저 암호의 변환을 쉽게 구현할 수 있다.
즉, 시저 암호에 최적화된 아스키 코드를 기반으로 로직을 구성한 것이다.

코드로 구현

class Solution {
    public String solution(String s, int n) {
        String answer = "";
        char[] chars = s.toCharArray();
        
        for(char c : chars) {
            if(Character.isUpperCase(c)) {
                char shifted = (char)(((int)c - 65 + n) % 26 + 65);
                answer += shifted;
            }
            else if(Character.isLowerCase(c)) {
                char shifted = (char)(((int)c - 97 + n) % 26 + 97);
                answer += shifted; 
            }
            else {
                answer += c;
            }
        }
        
        return answer;
    }
}

시간복잡도는 O(N)
N은 입력 문자열 s의 길이이다.
for 문에서 문자열의 길이만큼 순회하면서 각 문자를 변환하고 있다.

문자열을 문자 배열로 변환하여 접근 효율성을 높였다.
아스키 코드를 활용하여 변환 로직을 구현했다.

장점
문자열을 배열로 변경하여 랜덤 액세스 가능하다.
아스키 코드 기반으로 변환 로직이 단순하다.

단점
문자열을 배열로 복사하는 과정에서 추가 메모리 사용할 수 있다.
아스키 코드 계산으로 인한 다소의 성능 저하가 일어날수 있다.

내가 생각했을때 문제에서 원하는부분

정수를 저장한 배열, arr 에서 가장 작은 수를 제거한 배열을 리턴하는 함수
리턴하려는 배열이 빈 배열인 경우엔 배열에 -1을 채워 리턴
예를들어 arr이 [4,3,2,1]인 경우는 [4,3,2]를 리턴 하고, [10]면 [-1]을 리턴

내가 이 문제를 보고 생각해본 부분

입력 배열의 길이가 1이하이면 배열에 -1을 채운 새 배열을 리턴한다.
입력 배열의 최솟값을 구한다.
최솟값을 제외한 값들로 새 배열을 만든다.
새 배열을 리턴한다.

코드로 구현

import java.util.Arrays; 

class Solution {
    public int[] solution(int[] arr) {
        if (arr.length <= 1) 
            return new int[]{-1};

        int min = Arrays.stream(arr).min().getAsInt(); 
        return Arrays.stream(arr)
                     .filter(i -> i != min)
                     .toArray();
    }
}

시간복잡도는 O(N)

장점
코드가 간결해집니다. 기본 반복문과 index 처리 대신 배열 스트림만으로 처리가 가능하다.
가독성이 좋아진다. 데이터 흐름에 기반한 연산(filter, map 등)이 명확하다.
병렬 처리가 쉽다. .parallelStream()으로 손쉽게 병렬 처리 가능하다.

단점
성능 상 일반 반복문이 더 빠를 수 있다. 추가 래핑으로 인한 오버헤드가 발생할 수 있다.
람다와 스트림 문법에 익숙하지 않은 개발자가 이해하기 어려울 수 있다.

마무리

오늘 문제를 풀면서 아직 문제가 눈에 익숙치 않은것같다고 생각하게됐다. 생각을 조금더 곰곰히 해야할것같다. 코딩테스트를 준비하면서 적정 시간을 설정하고 풀어보는 것도 좋은 방법이 될것같다. 너무 많은 시간을 생각하는데 시간을 보내면 정작 코딩할 시간이 없을것같다.

profile
Junior backend developer

0개의 댓글