120923. 연속된 수의 합
2025. 9. 10. 18:39ㆍCS&알고리즘/프로그래머스
문제: 연속된 num개의 정수의 합이 total이 되도록 하는 수들을 찾아 배열로 반환
예시 1) num = 3, total = 12
출력: [3, 4, 5] → 3 + 4 + 5 = 12
예시 2) num = 5, total = 15
출력: [1, 2, 3, 4, 5] → 1 + 2 + 3 + 4 + 5 = 15
해결 방식
1. while 문을 이용한 무차별 대입 (바보 같았다..)
⚠️ 문제점
- 무한루프 위험
- 비효율성
- 복잡함
public int[] solution(int num, int total) {
int start = total / num; // 대략적인 시작점
while (true) {
int sum = 0;
for (int i = 0; i < num; i++) {
sum += start + i; // 연속된 수들의 합
}
if (sum == total) {
// 정답 찾음!
int[] answer = new int[num];
for (int i = 0; i < num; i++) {
answer[i] = start + i;
}
return answer;
}
// 합이 작으면 시작점을 높이고, 크면 낮춤
if (sum < total) {
start++;
} else {
start--;
}
}
}
2. 브루트 포스(완전 탐색)
Brute Force : 완전 탐색
: 가능한 모든 경우를 다 시도해보는 방법
특징
- 답이 있으면 반드시 찾아냄
- 복잡한 로직이 필요 없음
- 모든 경우를 다 확인하므로 비효율적
- 범위를 설정해야함
public int[] solution(int num, int total) {
// 범위 설정 (경험적 추정)
int minStart = total / num - num;
int maxStart = total / num + num;
// 설정한 범위에서 모든 시작점 시도
for (int start = minStart; start <= maxStart; start++) {
int sum = 0;
// 현재 시작점에서 연속된 num개 수의 합 계산
for (int i = 0; i < num; i++) {
sum += start + i;
}
// 합이 target과 같으면 정답!
if (sum == total) {
int[] answer = new int[num];
for (int i = 0; i < num; i++) {
answer[i] = start + i;
}
return answer;
}
}
return new int[]{}; // 해가 없는 경우
}
3. 등차수열
등차수열
: 연속된 두 항의 차이가 항상 같은 수열
예시 1: 1, 2, 3, 4, 5 (차이: 1)
예시 2: 3, 5, 7, 9, 11 (차이: 2)
예시 3: 10, 8, 6, 4, 2 (차이: -2)
등차수열의 구성 요소
- 첫째항: 수열의 첫 번째 수
- 공차: 연속된 항들의 차이
- 일반항: n번째 항의 공식
등차수열의 일반항 공식
첫째항을 a, 공차를 d라고 하면:
n번째 항 = a + (n-1) × d
등차수열을 이용하는 경우
- 데이터 분석 : 연속된 기간의 평균을 구할 때 (월별 매출 추이 분석)
- 게임 개발 : 레벨업 시스템의 경험치 계산 (1레벨 100XP, 2레벨 200XP, ...)
- 금융 : 적금의 월별 납입액 계산 (매월 일정 금액씩 증가하는 적금)
- 알고리즘 최적화 : O(n²) → O(n)으로 개선 (반복문 중첩 → 수식 한 번 계산)
등차수열을 문제에 적용하여 해결한다면 공차가 1인 등차수열로 계산
연속된 num개 수: a, a+1, a+2, ..., a+(num-1)
합 = a + (a+1) + (a+2) + ... + (a+num-1)
= num×a + (0+1+2+...+(num-1))
= num×a + num×(num-1)/2
따라서: total = num×a + num×(num-1)/2
정리하면: a = (total - num×(num-1)/2) / num
최종 코드 🎉
public int[] solution(int num, int total) {
// 등차수열 합 공식: 0+1+2+...+(num-1) = num×(num-1)/2
int arithmeticSum = num * (num - 1) / 2;
// 정수 해가 존재하는지 확인
if ((total - arithmeticSum) % num != 0) {
return new int[]{}; // 해가 없는 경우
}
// 시작값(첫째항) 계산
int start = (total - arithmeticSum) / num;
// 연속된 수들로 배열 생성
int[] answer = new int[num];
for (int i = 0; i < num; i++) {
answer[i] = start + i;
}
return answer;
}
레벨업 필요 경험치가 일정하게 증가하는 시스템의 예시 코드를 기반으로 등차수열이 실무에서 언제, 어떻게 코드에 녹아져서 사용되는지 한번 더 알아보기!
📈 상황 1: 레벨업 필요 경험치가 일정하게 증가하는 시스템
게임 기획:
- 1레벨 → 2레벨: 100XP 필요
- 2레벨 → 3레벨: 200XP 필요
- 3레벨 → 4레벨: 300XP 필요
- 매 레벨마다 100XP씩 증가
public class LevelSystem {
// 특정 레벨 달성에 필요한 총 경험치 계산
public int getTotalExpForLevel(int targetLevel) {
if (targetLevel <= 1) return 0;
// 등차수열의 합: 100 + 200 + 300 + ... + (targetLevel-1)*100
// = 100 × (1 + 2 + 3 + ... + (targetLevel-1))
// = 100 × (targetLevel-1) × targetLevel / 2
return 100 * (targetLevel - 1) * targetLevel / 2;
}
// 현재 경험치로 달성 가능한 레벨 계산
public int getCurrentLevel(int currentExp) {
int level = 1;
while (getTotalExpForLevel(level + 1) <= currentExp) {
level++;
}
return level;
}
// 다음 레벨까지 필요한 경험치
public int getExpToNextLevel(int currentExp) {
int currentLevel = getCurrentLevel(currentExp);
int totalExpForNext = getTotalExpForLevel(currentLevel + 1);
return totalExpForNext - currentExp;
}
}
🎯 상황 2: 스킬 업그레이드 비용이 등차수열로 증가
게임 기획:
- 스킬 1레벨 → 2레벨: 50골드
- 스킬 2레벨 → 3레벨: 100골드
- 스킬 3레벨 → 4레벨: 150골드
- 매 레벨마다 50골드씩 증가
public class SkillUpgradeSystem {
private static final int BASE_COST = 50;
// 특정 스킬 레벨까지 업그레이드하는 데 필요한 총 비용
public int getTotalUpgradeCost(int targetLevel) {
if (targetLevel <= 1) return 0;
// 등차수열의 합: 50 + 100 + 150 + ... + (targetLevel-1)*50
int n = targetLevel - 1;
return BASE_COST * n * (n + 1) / 2;
}
// 현재 골드로 업그레이드 가능한 최대 레벨
public int getMaxAffordableLevel(int currentGold, int currentSkillLevel) {
int currentTotalCost = getTotalUpgradeCost(currentSkillLevel);
int availableGold = currentGold + currentTotalCost;
// 이진 탐색으로 최대 레벨 찾기
int left = currentSkillLevel, right = 100;
int maxLevel = currentSkillLevel;
while (left <= right) {
int mid = (left + right) / 2;
if (getTotalUpgradeCost(mid) <= availableGold) {
maxLevel = mid;
left = mid + 1;
} else {
right = mid - 1;
}
}
return maxLevel;
}
}
'CS&알고리즘 > 프로그래머스' 카테고리의 다른 글
| [프로그래머스] 12939. 최댓값과 최솟값 (0) | 2025.10.10 |
|---|---|
| Lv.0 주사위 게임2 (1) | 2023.12.07 |
| Lv.0 코드 처리하기 (1) | 2023.12.06 |
| Lv.1 [PCCP 기출문제] 1번 (1) | 2023.12.05 |
| [프로그래머스] Lv.0 flag에 따라 다른 값 반환하기 (2) | 2023.12.03 |
