[문제 설명]
사탕이 담긴 N개의 주머니가 있다. 이 중 i (1≤i≤N) 번째 주머니에는 사탕이 ai개 들어 있다. 당신은 이 주머니 중 정확히 K개를 선택하여 어린이들에게 나누어 주려고 한다.
공정성을 위해, 당신은 나눠 준 주머니 가운데 사탕의 개수가 가장 많은 것과 가장 적은 것의 사탕 개수 차이를 최소화하려고 한다.
모든 유효한 방법 중 차이의 최솟값을 구하는 프로그램을 작성하라.
[입력]
첫 번째 줄에 테스트 케이스의 수 T가 주어진다.
각 테스트 케이스는 두 개의 줄로 이루어진다. 첫 번째 줄에는 주머니의 개수 N (2≤N≤50)과 나눠 줄 주머니의 개수 K (2≤K≤N)이 공백 하나를 사이로 두고 주어진다.
두 번째 줄에는 주머니 속 사탕의 개수를 나타내는 N개의 정수 a1,a2, ⋯ ,aN(1≤ai≤109)이 공백 하나씩을 사이로 두고 주어진다.
[출력]
각 테스트 케이스마다, 차이의 최솟값을 출력한다.
입력예제
| 3 3 2 1 2 3 3 3 5 20 10 4 3 4 3 2 1 |
출력예제
| #1 1 #2 15 #3 2 |
첫 번째 예제: 주머니 2개를 고르는 방법은 {1, 2}, {1, 3}, {2, 3}이 있다. 각각의 (최대) – (최소) 값은 1, 2, 1이다. 이 중 최솟값은 1이다.
두 번째 예제: 무조건 모든 주머니를 나눠줘야 한다.
[풀이]
첫번째 테스트케이스를 보면N = 3, K = 2사탕 바구니에 사탕은 각각 1 2 3 이 담겨 있습니다.
나올 수 있는 경우의 수는 {1,2}, {1,3}, {2,3} 이다. 여기서 사탕이 가장 많은 것 - 적은 것의 최솟값은 {1,2} 와 {2,3} 때문에 1이라는 최솟값이 나옵니다.
여기서 잘 생각해보면 정렬이 되어있다는 가정하 {1,3} 처럼 서로 붙어 있는 값이 아니라 떨어져 있는 값은 절대 최솟값이 나올 수가 없습니다.
왜냐하면, {1,2} 나 {2,3} 처럼 붙어 있어야만 최솟값이 나올 수 있기 때문입니다.
만약 N = 5, K = 3 이고 사탕 바구니에 사탕이 각각 1 100 101 102 200 이 담겨있다고 한다면

여기서 최솟값이 나올 수 있는 경우의 수는 {1, 100 ,101}, {100, 101, 102}, {101,102, 200} 인 경우 뿐.
1이라는 값이 포함되어 있을 때 아까처럼 붙어 있는 값이 아니라 떨어져 있는 값이 한 묶음이라면 나머지 2개의 값은 1에서 멀어지면 안됩니다.
즉, 1바로 다음값인 100 그리고 101이 들어와야 이 사탕이 가장 많은 것 - 가장 적은 것을 했을 때 최솟값이 될수 있습니다.
ex) {1,100,200}, {1, 101,102}의 최솟값은 각각 200-1 = 199, 102-1 = 101로 {1,100,101}의 101 - 1 = 100보다 큼
따라서 코딩을 할 때, 이 규칙성으로 반복문을 만들어야 합니다.저 문제에서의 답은 딱 봐도 {100, 101, 102} 로 102-100 인 2가 답입니다.
알고리즘 예시
N = 5, K = 3
1 100 101 102 200
for문으로 3개를 1묶음씩 3번 반복하면 값을 알 수 있습니다.
1. {1, 100, 101} 경우, 최솟값 = 100
2. {100, 101, 102} 경우, 최솟값 = 2
3. {101, 102, 200} 경우, 최솟값 = 99
따라서 100, 2, 99 중 가장작은 값인 2가 정답
밑에는 Java코드로 구현했습니다.
[Java code]
import java.util.Arrays;
import java.util.Scanner;
import java.io.FileInputStream;
class Solution{
public static void main(String args[]) throws Exception {
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
for (int tc = 1; tc <= T; tc++) {
int N = sc.nextInt();
int K = sc.nextInt();
long[] arr = new long[N];
for (int i=0; i<N; i++) arr[i] = sc.nextInt();
Arrays.sort(arr);//정렬
long result = 1000000000, max = 0, min = 0;
//result에는 사탕의 개수의 최대값인 10의 9승을 넣어주었다.
for (int i=0; i<=N-K; i++){
min = arr[i];//최솟값
max = arr[K-1+i];//최댓값
result = Math.min(max - min, result);
}
StringBuilder sb = new StringBuilder();
sb.append("#" + tc + " ");
sb.append(result);
System.out.println(sb);
}
}
}
코딩테스트 문제 풀이 설명을 처음 해보는 거라 엉망진창으로 설명한 거 같지만 이 문제가 이해가 안 되는 분들에게 도움이 되면 좋겠습니다.
'개발' 카테고리의 다른 글
| CORS 오류 (1) | 2025.07.08 |
|---|---|
| [Java] BAEKJOON 1074번 Z [실버1] (0) | 2024.05.08 |
| [Java] 백엔드 신입 개발자가 쌓아야 하는 역량 (feat. 자료구조, 알고리즘, 코딩테스트) (0) | 2024.04.04 |
| 앞으로의 백엔드 공부 계획 (feat. 백엔드 공부법) (0) | 2024.03.26 |
| [Java Heap] 자바 힙 개념 정리 (feat. 시간복잡도) (0) | 2024.03.23 |