Skip to main content

250821


코테

  • 다단계 칫솔판매 ok
  • [PCCP 기출문제] 3번 / 충돌위험 찾기

쉬운거

  • 콜라츠 추측 ok
  • 핸드폰 번호 가리기 ok
  • 가운데 글자 가져오기 ok
  • 나누어 떨어지는 숫자 배열 ok
  • 수 내림차순으로 배치하기 ok
  • 서울에서 김서방 찾기 ok
  • 핸드폰 번호 가리기 ok
  • 제일 작은 수 제거하기 ok
  • 내적 ok
  • 수박수박수박수박수박수? ok
  • 약수의 개수와 덧셈 ok
  • 부족한 금액 계산하기 ok
  • 문자열 내림차순으로 배치하기 ok -
  • 문자열 다루기 기본 ok


수 내림차순으로 배치하기

import java.util.Arrays;

class Solution {
    public long solution(long n) {
        StringBuilder sb = new StringBuilder();
        // 숫자 → 문자열 → char 배열
        char[] numArray = Long.toString(n).toCharArray();
        // 오름차순 정렬
        Arrays.sort(numArray);
        // 뒤에서부터 내림차순으로 붙이기
        for (int i = numArray.length - 1; i >= 0; i--) {
            sb.append(numArray[i]);
        }
        
        // 다시 long 타입으로 변환
        return Long.parseLong(sb.toString());
    }
}


나누어 떨어지는 숫자 배열

import java.util.*;

class Solution {
    public int[] solution(int[] arr, int divisor) {
        List<Integer> numList = new ArrayList<>();
        
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] % divisor == 0) {
                numList.add(arr[i]);
            }
        }
        
        if (numList.isEmpty()) {
            return new int[]{-1};
        }
        
        
        Collections.sort(numList);
        
        return numList.stream().mapToInt(Integer::intValue).toArray();
    }
}


서울에서 김서방 찾기

class Solution {
    public String solution(String[] seoul) {
        int idx = 0;
        for (int i = 0; i < seoul.length; i++) {
            if (seoul[i].equals("Kim")) {
                idx = i;
                break; // 김서방 찾으면 뒤에는 더 볼 필요 없음
            }
        }
        
        // 포매팅
        return String.format("김서방은 %d에 있다", idx);        
    }
}
import java.util.Arrays;

class Solution {
    public String solution(String[] seoul) {
        int idx = Arrays.asList(seoul).indexOf("Kim");
        return String.format("김서방은 %d에 있다", idx);
    }
}

Arrays.asList(배열명).indexOf("찾는문자열") 하면 한줄이구나... 이걸 스트림으로 하면

import java.util.stream.IntStream;

class Solution {
    public String solution(String[] seoul) {
        // 0부터 seoul.length-1까지 인덱스 스트림 생성
        int idx = IntStream.range(0, seoul.length)
                           .filter(i -> "Kim".equals(seoul[i]))
                           .findFirst()  // 첫 번째 일치 인덱스
                           .orElse(-1);  // 없으면 -1 반환 (안 나올 경우 대비)
        
        return String.format("김서방은 %d에 있다", idx);
    }
}


핸드폰 번호 가리기

이건 처음에 replace 메서드를 인덱스 범위로 잡아서 치환하려고 함

하지만 자바 String 클래스의 replace 메서드는 범위나 인덱스를 지정해서 치환하는 건 불가능하고,

해당 문자나 문자열만 특정 문자로 치환 가능

String.replace(char oldChar, char newChar); // 문자 치환
String.replace(CharSequence target, CharSequence replacement); // 문자열 단위 치환

즉 '0번~ 끝-4번 인덱스까지' *로 바꾸고 마지막 4자리는 그대로 같은 범위 치환은 직접 구현할 수 없음

대신

1. substring + StringBuilder

class Solution {
    public String solution(String phone_number) {
        int len = phone_number.length();
        StringBuilder sb = new StringBuilder();
        
        // 앞의 (len - 4)자리까지 *로 채우기
        for (int i = 0; i < len - 4; i++) {
            sb.append("*");
        }
        
        // 뒤 4자리는 그대로 붙이기
        sb.append(phone_number.substring(len - 4));
        
        return sb.toString();
    }
}

2. 정규식 + replaceAll (범위 치환)

class Solution {
    public String solution(String phone_number) {
        return phone_number.replaceAll("\\d(?=\\d{4})", "*");
    }
}
  1. \\d
    • 숫자 한자리
    • [0-9]랑 동일
    • 예: "123"에서 \\d는 '1', '2', '3' 각각 매치됨
  2. (?=...) positive lookahead 긍정적 전방 탐색
    • 앞 쪽에 특정 패턴이 있는지 확인만 하고, 실제로 매치에는 포함하지 않음
    • 예:"a1b2c3"에서 "\\d(?=b)"
    • '1' 다음이 'b'라서 '1'만 매치됨
    • '2', '3'은 매치 안 됨
  3. \\d{4}
    • 숫자 4자리 연속을 의미한다
    • 예: "1234" 전체와 매치됨
    • {n}은 반복 횟수
  4. \\d(?=\\d{4}) 합쳐서 보면
    • "뒤에 4자리 숫자가 있는 숫자 한 자리"
      • '0' 뒤에 4자리 숫자가 있나? → 맞으면 매치 → *로 변환
      • '1' 뒤에 4자리 숫자가 있나? → 맞으면 매치 → *로 변환
      • 마지막 4자리는 뒤에 4자리 숫자가 없으므로 매치 안 됨 → 그대로


제일 작은 수 제거하기

import java.util.*;

class Solution {
    public int[] solution(int[] arr) {
        if (arr.length == 1) {
            return new int[]{-1};
        } 
        
        int min = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] < min) {
                min = arr[i];
            }
        }
        
        int[] answer = new int[arr.length - 1];
        int idx = 0;
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] != min) {
                answer[idx++] = arr[i];
            }
        }
        
        return answer;
    }
}
import java.util.*;

class Solution {
    public int[] solution(int[] arr) {
        if (arr.length == 1) {
            return new int[]{-1};
        } 
      
        // 배열에서 가장 작은 수를 min에 저장
        int min = Arrays.stream(arr) // 배열을 스트림으로 바꾸기
                        .min() // min으로 최소값 구하기
                        .getAsInt(); // OptionalInt 타입으로 나옴. getAsInt()로 실제 최소값 꺼내기

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


콜라츠 추측

class Solution {
    public int solution(int num) {
        int cnt = 0;
        while(cnt < 500) {
            if (num % 2 == 0) {
                num = num/2;
                cnt++;
            } else if (num % 2 == 1) {
                num = num *3 + 1;
                cnt++;
            }
            if (num == 1) {
                return cnt;
            }
        }
        
        return -1;
    }
}

시간초과 나는 이유

  1. int 오버플로우 위험
    • num * 3 + 1 하면 int 범위 넘어갈 수 있다. (int는 약 21억까지만 가능)
    • 그래서 long을 써야 안전하다
  2. 불필요한 연산
    • if (num % 2 == 0) → else 로 충분한데 else if 로 조건을 다시 검사하고 있다.
    • 자바에서 % 연산은 나름 무겁기 때문에 조금이라도 줄이는 게 좋다.
class Solution {
    public int solution(int num) {
        long n = num; 
        int cnt = 0;
        while(n != 1 && cnt < 500) {
            if (n % 2 == 0) {
                n = n/2;
            } else {
                n = n *3 + 1;
            }
            cnt++;
        }
        
        return (n == 1) ? cnt : -1;
    }
}

수정내용

  • cnt++ if문 밖으로 뺌
  • 삼항 연산자로 처리
  • while문 조건 n이 1이 아니면서 cnt가 500보다 작을 때

시간 초과 원인이 int 오버 플로우 때문이다
else는 사실상 성능 영향 거의 없다 (가독성 문제)
오버플로우가 일어나면 음수나 엉뚱한 값이 되고, 결국 1에 도달하지 못해 무한루프 비슷하게 된다.
그럼 while(cnt < 500) 때문에 계속 500번 반복하고 모든 테스트케이스에서 불필요한 연산이 이루어짐...
그래서 long을 써야 정상적으로 수렴 여부 체크 가능...


약수의 개수와 덧셈

class Solution {
    public int solution(int left, int right) {
        int answer = 0;
        for (int i = left; i <= right; i++) {
            int cnt = 0; // 위치 중요 for문 바깥이면 i 초기화 안됨
            for (int j = 1; j <= i; j++) {
                if (i % j == 0) {
                    cnt++;
                }
            }
            if (cnt % 2 == 0) {
                answer += i;
            } else {
                answer -= i;
            }
        }
        
        return answer;
    }
}


문자열 내림차순으로 배치하기

import java.util.*;

class Solution {
    public String solution(String s) {
        char[] str = s.toCharArray();
        Arrays.sort(str);
        
        // 내림차순으로 뒤집기
        for (int i = 0; i < str.length / 2; i++) {
            char temp = str[i];
            str[i] = str[str.length - 1 - i];
            str[str.length - 1 - i] = temp;
        }
        
        return new String(str); // str.toString(); x
    }
}

스트림

import java.util.*;

class Solution {
    public String solution(String s) {
        return s.chars() // IntStream
                .mapToObj(c -> (char)c)
                .sorted(Comparator.reverseOrder())
                .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append)
                .toString();
    }
}

배열 뒤집기 없이

import java.util.*;

class Solution {
    public String solution(String s) {
        char[] str = s.toCharArray();
        // 내림차순 정렬: 오름차순 후 Comparator 사용 없이 바로 정렬
        // Integer로 변환 후 내림차순 정렬
        Character[] chars = new Character[str.length];
        for (int i = 0; i < str.length; i++) chars[i] = str[i];

        Arrays.sort(chars, Collections.reverseOrder());

        StringBuilder sb = new StringBuilder();
        for (char c : chars) sb.append(c);

        return sb.toString();
    }
}


문자열 다루기 기본

class Solution {
    public boolean solution(String s) {
        // 길이가 4 또는 6이 아니면 false
        if (s.length() != 4 && s.length() != 6) {
            return false;
        }
        
        // 숫자인지 확인
        for (int i = 0; i < s.length(); i++) {
            if (!Character.isDigit(s.charAt(i))) {
                return false;
            }
        }
        
        return true;
    }
}




농협 KT, 웹하드 ok

슬리퍼 세탁

속눈썹펌 예약

피그먼트 반품 - 뷔스티에

PC 워런티 기간 업데이트 확인 ok

내꺼 테디테일즈 레나베어 키링 상어 옷 ok