문제
https://school.programmers.co.kr/learn/courses/30/lessons/120843


풀이
1. 수식 측
class Solution {
public int solution(int[] numbers, int k) {
// (k - 1) * 2번 이동 후 위치를 numbers 길이로 나눈 나머지가 최종 인덱스
int index = ((k - 1) * 2) % numbers.length;
return numbers[index];
}
}
왜 2씩 곱하는지
- k번째 사람이 누구인지 찾기 위함
- 공은 오른쪽으로 한 명 건너서 던짐 → 매번 2칸 이동
- 예: 0 → 2 → 4 → 6 → ...
- 즉, 공을 던질 때마다 인덱스는 +2씩 증가
- 그래서 2를 곱함
(k - 1) * 2 → 이동한 총 칸 수
- k - 1인 이유
- 첫 번째 사람(1번)은 공을 받은 게 아니라 시작자니까, 실제 이동은 k - 1번
왜 length로 나누는지 (즉, ... % numbers.length)
- 배열은 원형 구조
- 즉, 끝까지 가면 처음으로 다시 돌아와야 함
인덱스: 0 1 2 3
사람 번호: 1 2 3 4
이동 인덱스:
0 → 2 → 4 → 6 → 8 → ...
→ 배열은 길이 4니까, 4 이상 되면 다시 처음부터 시작
→ 인덱스 4 % 4 = 0
→ 인덱스 6 % 4 = 2
→ 인덱스 8 % 4 = 0
- 그래서 % numbers.length를 해주면 배열 크기를 넘지 않게 순환할 수 있음
우리가 구하는 건 몫이 아니라 나머지
int index = ((k - 1) * 2) % numbers.length;
- ((k - 1) * 2) → 총 이동한 거리
- % numbers.length → 순환 배열에 맞게 인덱스 조정 (배열을 넘기지 않도록)
- 즉, 몫이 아니라 현재 위치 인덱스를 구하는 것
요약
| 항목 | 설명 |
| 곱하기 2의 역할 | 한 명 건너서 공을 던지니까, 인덱스가 한 번에 2씩 증가하는 것을 계산하기 위함 |
| % length 의 역할 | 원형 배열이기 때문에, 배열의 끝을 넘어갈 경우 다시 처음으로 돌아오기 위함 |
| 나머지의 역할 | 나머지를 구해서 현재 위치(인덱스)를 계산 |
직관 공식 요약
index = ((k - 1) * 2) % numbers.length;
- (k - 1): 던진 횟수
- * 2: 한 번에 두 칸씩 이동
- % numbers.length: 원형 배열 처리 (인덱스가 넘지 않도록)
2. 가독성 측면
class Solution {
public int solution(int[] numbers, int k) {
int index = 0; // 시작은 1번, 즉 numbers[0]
for (int i = 1; i < k; i++) {
index += 2; // 오른쪽 한 명 건너서 던지기
if (index >= numbers.length) {
index -= numbers.length; // 원형 구조라 넘으면 되돌림
}
}
return numbers[index];
}
}
예제 설명 (numbers = [1, 2, 3], k = 3)
- 시작 index = 0 → numbers[0] = 1
- 첫 번째 던짐: index = 0 + 2 = 2 → numbers[2] = 3
- 두 번째 던짐: index = 2 + 2 = 4 → 초과하므로 index = 4 - 3 = 1 → numbers[1] = 2
- 이제 3번째 던진 사람이 누구냐? → index = 1 → numbers[1] = 2
순환 배열
- 배열 끝에 도달하면 다시 처음으로 돌아가는 구조
- 이걸 원형 구조 (circular structure) 라고 함
예: 배열이 [1, 2, 3, 4]이고, 인덱스가 0부터 3까지라고 가정해보자
- 0번째 → 1
- 1번째 → 2
- 2번째 → 3
- 3번째 → 4
- 그 다음? → 다시 0번째로 돌아가야 함 → 순환
왜 나머지가 인덱스가 되는가?
예: 공을 총 6칸 이동했다고 가정해보자. 배열 길이는 4 (즉, numbers.length = 4)
int moved = 6;
int index = moved % 4; // 결과: 2
- 왜 2번 인덱스가 현재 위치일까요?
나머지가 인덱스가 되는 이유
- 나머지는 배열 내에서의 실제 위치를 나타내기 때문
- 배열의 범위는 0 ~ length - 1 이고, 이동 칸 수가 아무리 커져도 이 범위를 벗어나면 안 되기 때문에,
- 나머지 연산 (%)은 배열 범위 안으로 값을 자동 조절해줌
예: 배열: [1, 2, 3, 4], 길이: 4 (numbers.length = 4)
- 총 이동 칸수 → 실제 위치 (인덱스)
| 이동 칸수 | 나머지 (% 4) | 배열 인덱스 | 값 |
| 0 | 0 | 0 | 1 |
| 1 | 1 | 1 | 2 |
| 2 | 2 | 2 | 3 |
| 3 | 3 | 3 | 4 |
| 4 | 0 | 0 | 1 |
| 5 | 1 | 1 | 2 |
| 6 | 2 | 2 | 3 |
- 이동 칸수 % 배열 길이 = 실제 인덱스
- 즉, 배열 밖으로 나가도 걱정 없음, 나머지만 취하면 항상 배열 내 인덱스가 되기 때문
'Algorithm > Programmers' 카테고리의 다른 글
| [Programmers] Lv.0 | 점의 위치 구하기 | Java (0) | 2025.10.19 |
|---|---|
| [Programmers] Lv.0 | 2차원으로 만들기 | Java (0) | 2025.10.18 |
| [Programmers] Lv.0 | 배열 회전시키기 | Java (0) | 2025.10.16 |
| [Programmers] Lv.0 | 주사위의 개수 | Java (0) | 2025.10.15 |
| [Programmers] Lv.0 | 합성수 찾기 | Java (0) | 2025.10.14 |
댓글