1937년 Collatz가 제기한 추측으로, 주어진 수가 1이 될 때까지 아래 작업을 반복하면 모든 수를 1로 만들 수 있다는 추측이다.
n / 23n + 1작업을 몇 번 반복해야 1이 되는지 반환하는 함수를 작성한다.
예시
6 → 3 → 10 → 5 → 16 → 8 → 4 → 2 → 1 (총 8번)
제한 조건
0 반환-1 반환class Solution {
public int solution(int num) {
int answer = 0;
while(true){
if(num==1){
answer=0; // ❌ break 없음
}
if(num%2==0){
num=num/2;
answer++;
}else if(num%2==1){
num=(num*3)+1;
answer++;
}
if(answer>=500){
answer=-1;
break;
}
if(num==1){
break;
}
}
return answer;
}
}
문제점 1 - break 누락
num=1로 시작하면 answer=0 초기화만 하고 루프를 탈출하지 않는다.
이후 홀수 조건(1%2==1)에 걸려 num=4가 되고 루프가 계속 돈다.
문제점 2 - int 오버플로우
626331 케이스에서 num * 3 + 1 연산 중간에 int 범위(약 21억)를 초과하는 값이 발생한다.
오버플로우가 나면 num이 음수가 되고, num==1 조건을 영원히 만족하지 못해 무한루프(10초 이상 멈춤) 에 빠진다.
if(num==1){
answer=0;
break; // ✅ break 추가
}
num=1 예외는 해결했지만 오버플로우 문제는 아직 남아있다.
class Solution {
public int solution(int num) {
int answer = 0;
long targetNum = num; // ✅ long으로 오버플로우 방지
while(targetNum > 1){ // ✅ num=1 예외처리 겸용
if(targetNum % 2 == 0){
targetNum = targetNum / 2;
} else {
targetNum = (targetNum * 3) + 1;
}
answer++;
if(answer >= 500){
answer = -1;
break;
}
}
return answer;
}
}
while(targetNum > 1) 조건 자체가 num=1 예외처리 역할을 겸한다.
num=1로 시작하면 루프에 진입하지 않고 answer=0을 그대로 반환한다.
int vs long
| 타입 | 최댓값 | 비고 |
|------|--------|------|
| int | 약 21억 | 오버플로우 → 음수 → 무한루프 |
| long | 약 922경 | 콜라츠 중간값 안전하게 처리 가능 |
반환값이 int여도 내부 연산 변수는 long 으로 선언하는 것이 안전하다.
n * 3,n * n처럼 값이 반복적으로 커지는 구조가 보이면long타입을 먼저 고려하자.
정확한 최댓값 계산이 어려운 구조일수록long으로 선언하고 시작하는 게 안전하다.
전화번호 문자열에서 뒷 4자리를 제외한 나머지를 전부 *로 가린 문자열을 반환한다.
예시
"01033334444" → "*******4444"
"027778888" → "*****8888"
제한 조건
phone_number 길이: 4 이상 20 이하class Solution {
public String solution(String phone_number) {
int frontNumberLeng = phone_number.length() - 4;
String frontNumber = phone_number.substring(0, frontNumberLeng);
String backNumber = phone_number.substring(frontNumberLeng, phone_number.length());
frontNumber = frontNumber.replaceAll("[0-9]", "*"); // 불필요한 정규식
return frontNumber + backNumber;
}
}
개선 포인트
frontNumber는 어차피 전부 *로 바꿔야 하는 문자열이다.
정규식으로 숫자를 하나씩 치환할 필요 없이, 길이만큼 *를 채우면 된다.
class Solution {
public String solution(String phone_number) {
int len = phone_number.length() - 4;
return "*".repeat(len) + phone_number.substring(len);
}
}
String.repeat(n)
Java 11부터 지원하는 문자열 반복 메서드.
"*".repeat(7) → "*******"
반복문이나 정규식 없이 한 줄로 처리 가능하다.
substring(n)
끝까지 자를 때는 두 번째 인자 생략 가능.
phone_number.substring(len, phone_number.length()) // 동일
phone_number.substring(len) // ✅ 간결
Java는 파이썬과 달리 음수 인덱스를 지원하지 않는다.
뒤에서 n자리는substring(length - n)으로 처리해야 한다.