두 정수 a, b가 주어졌을 때 a와 b 사이에 속한 모든 정수의 합을 리턴
등차수열 합 공식
S = (첫째항 + 마지막항) * 항의 개수 / 2
a, b 사이의 정수 합이니까:
S = (a + b) * (|a - b| + 1) / 2
import java.lang.Math;
class Solution {
public long solution(int a, int b) {
long answer = 0;
answer = (long)(a + b) * (long)(Math.abs(a - b) + 1) / 2;
return answer;
}
}
① 나눗셈 순서 주의
처음에 이렇게 짰다가 버그 발생:
answer = (a + b) / 2 * (Math.abs(a - b) + 1); // ❌
Java 정수 나눗셈은 소수점을 버리기 때문에 (a + b)가 홀수면 오차 발생.
a=3, b=4일 때:
(3 + 4) / 2 * 2 = 3 * 2 = 6 // 기대값은 7!
→ 곱셈 먼저, 나눗셈 나중으로 순서 변경:
answer = (a + b) * (Math.abs(a - b) + 1) / 2; // ✅
② 왜 항상 2로 나눠떨어지나?
(a + b)와 (|a - b| + 1) 두 값의 홀짝성은 항상 반대.
| a | b | a+b | |a-b|+1 |
|---|---|---|---|
| 3 | 5 | 8 (짝) | 3 (홀) |
| 3 | 4 | 7 (홀) | 2 (짝) |
| 4 | 6 | 10 (짝) | 3 (홀) |
→ 홀수 × 짝수는 항상 짝수 (짝수 = 2의 배수이므로, 곱 안에 2가 항상 포함됨)
→ 따라서 항상 2로 나눠떨어짐이 보장됨
③ long 캐스팅으로 오버플로우 방지
a, b 최대값이 10,000,000이므로 중간 계산값이 int 범위를 초과할 수 있음.
(long)(a + b) * (long)(Math.abs(a - b) + 1) / 2
class Solution {
public long solution(int a, int b) {
return sumAtoB(Math.min(a, b), Math.max(b, a));
}
private long sumAtoB(long a, long b) {
return (b - a + 1) * (a + b) / 2;
}
}
| 내 풀이 | 다른 풀이 | |
|---|---|---|
| 대소처리 | Math.abs() | Math.min/max로 사전 정렬 |
| 구조 | 단일 메서드 | 책임 분리 (정렬 / 계산) |
| 가독성 | 보통 | sumAtoB 이름만 봐도 의도 파악 가능 |
→ 메서드로 분리하면 관심사 분리가 되어 가독성이 올라감
대문자와 소문자가 섞인 문자열 s에서 'p'의 개수와 'y'의 개수를 비교해 같으면 true, 다르면 false 리턴
① 문자열 전체를 소문자로 변환 후 순회
s.toLowerCase()
→ 미리 소문자로 변환하면 이후 비교가 단순해짐
② split("") 대신 toCharArray() 사용
// ❌ split("") - 정규식 엔진 오버헤드 발생
String[] strArr = s.split("");
// ✅ toCharArray() - 단순 char 배열 변환, 더 효율적
char[] charArr = s.toCharArray();
③ 삼항연산자 대신 boolean 직접 반환
return cntP == cntY ? true : false; // ❌ 불필요한 삼항연산자
return cntP == cntY; // ✅ == 비교 자체가 boolean 반환
class Solution {
boolean solution(String s) {
int cntP = 0;
int cntY = 0;
char[] charArr = s.toCharArray();
for (char c : charArr) {
char lower = Character.toLowerCase(c);
if (lower == 'p') {
cntP++;
} else if (lower == 'y') {
cntY++;
}
}
return cntP == cntY;
}
}
| 항목 | 변경 전 | 변경 후 | 이유 |
|---|---|---|---|
| 문자열 순회 | split("") | toCharArray() | 정규식 오버헤드 제거 |
| 대소문자 처리 | equalsIgnoreCase() | Character.toLowerCase() | 미리 변환 후 단순 비교 |
| 반환 | cntP==cntY ? true : false | cntP==cntY | == 자체가 boolean |
| for문 | for(int i=0; i<arr.length; i++) | for(char c : arr) | enhanced for문으로 간결하게 |
뭔가 간결하게 풀어보고 싶은데 한참 멀은듯.
다른 사람들이 푼거보니까 비슷한것도 많은데 저렇게 깔끔하게 처리한 것도 많았음. 좀 더 깔끔하게 풀 수 있도록 노력해야겠음.