오늘의 학습 키워드
</> 이분탐색
공부한 내용 본인의 언어로 정리하기
class Solution {
public int arrangeCoins(int n) {
long low = 1;
long high = n;
while(low <= high){
long mid = low + (high - low) / 2;
long sum = mid * (mid + 1) / 2;
if(sum > n){
high = mid - 1;
} else {
low = mid + 1;
}
}
return (int)high;
}
}
오늘의 회고
오늘 주제도 이분탐색이므로 어제 공부한 이분탐색을 이용해서 문제를 풀어보았다. 차이점은 반환값에 low
가 아닌 high
가 사용된 것과 주어진 값이 배열이었던 것과 다르게 정수n
으로 주어졌다.
오늘 low
가 아닌 high
를 이용한 이유와 탐색의 조건이 sum > n
인 이유는 아래에서 설명하겠다.
시작은 모든 값을 int
로 사용해서 작성했었지만 코드 제출후 테스트과정에서 큰 값이 나와 실패된 후 모든 값을 long
으로 변경하고 제출해야할 값만 int
로 형변환을 해주었다.
long low = 1;
long high = n;
low
는 탐색의 시작점으로 최소 계단의 수는 1개 이므로 1로 초기화를 해주었고 high
는 탐색의 상한선으로 계단이라는 정의에는 맞지않지만 1개씩 쌓아서 계단을 만든다고 가정했을때 탐색할 수 있는 최대의 값이 주어진 동전의 값이므로 n
으로 저장을 해주었다.
이후는 이분탐색의 공식에 맞게 작성하였다. low
가 high
보다 작거나 같을때 까지만 반복 탐색을 해주도록 하고 오늘의 mid
값은 중간 값이기도 하지만 주어진 동전을 이용해서 만들 수 있는 잠재적인 최대 계단의 수를 나타내고sum
은 그 최대 계단의 수에 필요한 최대 동전의 개수를 가리킨다.
while(low <= high){
long mid = low + (high - low) / 2;
long sum = mid * (mid+1) / 2;
}
이후 이분탐색으로 범위를 점점 좁혀나가며 값을 찾아나가면 된다. 하지만 오늘은 동전으로 만들 수 있는 최대 계단의 수를 찾아야 하므로 최대의 계단을 만드는데 필요한 동전의 수와 주어진 동전의 수를 비교해서 탐색을 하였다. 만약 동전의 수가 부족해서 만드는게 불가능하다면 이전 계단을 탐색하고 동전의 수가 많아서 가능하다면 다음 계단을 탐색하였다.
그렇게 되면 high
는 탐색된 범위 내에서 주어진 n
개의 동전으로 완전히 채울 수 있는 최대 계단의 수가 되며 low
는 탐색된 범위 내에서 다음 계단을 만드는 것을 시도할 수 있는 위치, 즉 이 위치는 아직 검증되지 않은 상태로, 실제로는 n
개의 동전으로 채울 수 없는 최초의 계단의 순서가 되는 것이다.
결론적으로 high
는 완성할 수 있는 계단의 수, low
는 완성할 수 없는 최초의 계단의 순서가 된다.
if(sum > n){
high = mid - 1;
} else {
low = mid + 1;
}
최종적으로 우리는 완성할 수 있는 계단의 수를 구해야 하므로 high
를 반환해준다. 여기서 우리는 앞서 모든 값들을 long
으로 생성해왔지만 반환은 int
로 반환을 해야하므로 형변환을 해준다.
return (int)high;
아직 이분탐색의 원리를 100% 깨닿지 못했지만 문제를 풀고 공부를 하면서 점점 원리를 체감하며 깨달아가는 중이다. 문제를 많이 풀어야 코테가 수월해진다는 말이 확실히 체감이 되는 것 같다. 스터디가 얼마 남지 않았지만 종료 후에도 꾸준히 해야겠다는 의지가 점점 다져지는 것 같다.
AI 코드리뷰
현재 코드의 장점
현재 코드의 단점
long
타입을 사용하여 계산하고 int
로 캐스팅하여 반환합니다. 이 문제에서 int
로도 충분하지만, long
타입을 사용하는 이유가 필요하지 않을 수 있습니다.low
와 high
값이 int
범위를 초과하는 경우를 고려하지 않았습니다.시간 복잡도
개선할 점
low
, high
, mid
를 int로 처리하여 코드의 간결성을 높일 수 있습니다.long
타입의 계산을 int
로 변경하여 코드를 간결하게 만들 수 있습니다.class Solution {
public int arrangeCoins(int n) {
int low = 1;
int high = n;
while (low <= high) {
int mid = low + (high - low) / 2;
long sum = (long)mid * (mid + 1) / 2;
if (sum > n) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return high;
}
}
개선된 버전의 장점
long
을 사용하는 부분을 최소화하고, int
타입을 사용하여 간결성을 높였습니다.long
으로 캐스팅하여 계산 결과의 범위 문제를 피하면서도 int
타입으로 간결하게 유지했습니다.개선된 버전의 단점
long
타입 사용: 동전 수가 int
의 범위를 넘지 않는다고 가정하면, long
을 사용하는 것이 오히려 과할 수 있습니다. 하지만 이 문제의 조건에서는 큰 입력이 필요할 경우도 있을 수 있으므로 long
을 유지하는 것이 더 안전할 수 있습니다.시간 복잡도
내일 공부할 것 :
이분탐색의 결과의 여러 경우에서 어떻게 사용하는지 알아보고 과정에 대해서 확실히 이해해보자.
문제
멋쪄용~~