[99클럽 2일차] [프로그래머스] Lv.0 크기가 작은 부분문자열

Dev.Dana·2024년 10월 29일
0

Algorithm

목록 보기
7/25
post-thumbnail
💡 멍청이 손 들어! 넵 🤚🏻

바보 같은 생각으로 코드를 3번이나 짜버린 오늘을 반성하기 위해 위 코테문제 후기를 남겨보고자 한다.

첫 번째 코드 : 내 생각대로 손이 가는대로

programmers 크기가 작은 부분문자열

위 문제를 처음 봤을 때 그냥 바로 머릿속에 그려지는대로 코드를 작성했다.

내가 접근한 방식은 p 크기별로 t 를 잘라서 배열에 담은 후 하나씩 비교해서 t가 p보다 작거나 같다면 answer를 하나씩 늘려주는 것이었다.

class Solution {
    public int solution(String t, String p) {
        int answer = 0;
        
        int tl = t.length();
        int pl = p.length();
        int intp = Integer.parseInt(p);
        
        int[] arr = new int[tl - pl + 1];
        
        for(int i=0; i<tl-pl+1; i++){
            arr[i] = Integer.parseInt(t.substring(i, i+pl));
        }
        
        for(int i : arr){
            if(i<=intp) answer++;
        }
        return answer;
    }
}

막상 코드를 작성하고 문제를 천천히 다시 보니 배열에 담아야 할 필요가 없는데 왜 저랬을까? 하는 생각에 다시 작성했다.

두 번째 코드 : 불필요한 부분은 삭제

class Solution {
    public int solution(String t, String p) {
        int answer = 0;
        
        int tl = t.length();
        int pl = p.length();
        long intp = Integer.parseInt(p); 
        
        // 정수 배열 대신 바로 비교
        for (int i=0; i<=tl-pl+1; i++) { 
            long num = Integer.parseInt(t.substring(i, i + pl)); 
            if (num <= intp) answer++;
        }
        
        return answer;
    }
}

자. 이제 코드도 깔끔해졌고 정답이겠지? 하고 제출을 누른 순간 성공 사이에 보이는 빨간 글씨들… 런타임 에러란다…

세번째 코드 : 문제 이해를 똑바로 하자

문제를 다시 읽어봤다. 왜 에러가.. 나…? 이러면서ㅋㅋㅋ

🚨 제한 사항을 꼭 읽도록 하자. **범위, 시간** 이런거 안지키다간 코테 합격은 불가능이다 !

문제를 다시 이해해보자

  1. t에서 p와 같은 길이의 부분 문자열들을 하나씩 슬라이딩 윈도우방식으로 추출해서 그 값이 p보다 작거나 같은지 비교하는 문제
  2. 처음엔 숫자 비교라고 하니 당연하게 int로 변환했지만 범위를 잘 보자.
    • int는 -21억xxx부터 21억xxx까지 최대 10자리의 수만 담을 수 있다.
    • 제한 사항에 p의 길이가 최대 18이라고 쓰여있다. → int로는 커버 불가.

코드를 long 타입을 이용해 다시 작성해보았다.

class Solution {
    public int solution(String t, String p) {
        int answer = 0;
        
        int tl = t.length();
        int pl = p.length();
        long intp = Long.parseLong(p); // p의 값을 long으로 변환
        
        // 정수 배열 대신 바로 비교
        for (int i=0; i <= tl-pl+1; i++) {
            long num = Long.parseLong(t.substring(i, i + pl)); // 부분 문자열을 long으로 변환
            if (num <= intp) answer++;
        }
        return answer;
    }
}

이제서야 전체 성공의 결과를 받았다.

추가로

다른 사람의 풀이를 좀 구경해봤는데 생각해보니 compareTo() 로 비교해도 좋은 것 같다.

→ compareTo 를 사용하면 문자열을 바로 비교할 수 있기 때문에 형변환도 필요없다 !!

if (subStr.compareTo(p) <= 0) {
    answer++;
}

숫자가 매우 클 때는 문자열을 그대로 비교해버리는 방식이 더 효율적이다. 문자열의 사전식 비교는 compareTo 메소드를 이용하면 됐는데 문제 풀 때는 아는 함수더라도 잘 기억이 나질 않았다.

역시 함수들은 자주 자주 써보는게 문제 보면 바로 생각나게 하는 방법인 듯 하다.

+ 슬라이딩 윈도우

•	구간의 크기는 고정되어 있고 이 구간을 데이터 전체를 따라 이동시키면서 계산을 진행한다.
•	매번 윈도우를 옮길 때 이전 구간의 계산을 재활용할 수 있어서 반복적인 계산을 줄여 시간 복잡도를 개선할 수 있다는 장점이 있음
슬라이딩 윈도우 방식의 동작 원리
1.	첫 구간을 설정하고 그 구간의 값으로 초기 계산을 수행
2.	윈도우를 오른쪽으로 한 칸씩 이동시키면서, 새로운 구간의 계산을 수행
	이동할 때는 새로 추가된 요소와 제외된 요소만 업데이트 함
3.	전체 데이터에 대해 윈도우를 이동하면서 결과값을 구한다!
profile
어제의 나보단 나은 오늘의 내가 되기를

0개의 댓글