두개의 그룹으로 나누어 최소차이로 만들기

Mijeong Ryu·2023년 6월 15일
0

알고리즘

목록 보기
2/2

1)그리디 알고리즘

이 문제는 그리디 알고리즘과 정렬을 이용하여 해결할 수 있습니다. 주어진 수들을 절대값을 기준으로 정렬한 후, 큰 수부터 차례대로 두 그룹에 배분하면 됩니다. 배분하는 기준은 그룹의 합을 최소화하는 것입니다.

이를 Java 코드로 구현하면 다음과 같습니다.

java
Copy code
import java.util.*;

class Solution {
    public int solution(int[] numbers) {
        int sum1 = 0, sum2 = 0;
        Integer[] numbersCopy = Arrays.stream(numbers).boxed().toArray(Integer[]::new);
        Arrays.sort(numbersCopy, Comparator.comparingInt(Math::abs).reversed());

        for (int number : numbersCopy) {
            if (sum1 > sum2) {
                sum2 += number;
            } else {
                sum1 += number;
            }
        }

        return Math.abs(sum1 - sum2);
    }
}
먼저 입력 배열을 복사하면서 Integer 타입으로 바꾸고, 절대값을 기준으로 내림차순으로 정렬합니다. 그 다음으로 각 숫자를 큰 수부터 차례대로 두 그룹에 배분하는데, 그룹의 합이 작은 쪽에 배분합니다. 이렇게 모든 수를 배분한 후에 두 그룹의 합의 차이를 계산하여 반환하면 됩니다.

2)DP

이 문제는 Dynamic Programming(DP)을 활용하여도 풀 수 있습니다. 그룹의 합의 차이가 최소가 되려면 모든 원소의 합을 반으로 나눈 값과 가장 가까운 값을 구해야 합니다. DP를 이용하여 가능한 모든 합의 경우를 구하고 그 중에서 가장 원소의 합의 절반에 가까운 값을 찾아 그 차이를 반환하면 됩니다.

아래는 이를 구현한 Java 코드입니다:

import java.util.*;

public class Solution {
    public int solution(int[] A) {
        // Convert A to the absolute values of its elements
        for (int i = 0; i < A.length; i++) {
            A[i] = Math.abs(A[i]);
        }
        
        // Calculate the sum of elements in A
        int S = 0;
        for (int a : A) {
            S += a;
        }
        
        // Initialize a list to store the possible sums
        int[] dp = new int[S + 1];
        dp[0] = 1;
        
        // Calculate the possible sums
        for (int a : A) {
            for (int j = S; j >= 0; j--) {
                if (dp[j] == 1 && j + a <= S) {
                    dp[j + a] = 1;
                }
            }
        }
        
        // Find the minimum absolute value of the sums
        int result = S;
        for (int i = 0; i <= S / 2; i++) {
            if (dp[i] == 1) {
                result = Math.min(result, S - 2 * i);
            }
        }
        
        return result;
    }
}
이 코드는 입력받은 숫자들의 절대값의 합을 계산한 후, 그 합을 2로 나눠 반값(halfSum)을 구합니다. 그리고 가능한 모든 합을 저장할 boolean 배열을 선언합니다. 이 배열의 인덱스는 합을, 값은 그 합이 가능한지 여부를 나타냅니다. 그 다음 숫자들을 순회하면서 해당 숫자를 포함하여 만들 수 있는 합을 dp 배열에 표시합니다. 마지막으로 dp 배열을 반값부터 내림차순으로 검사하여 첫 번째 true 값을 찾으면 그 인덱스가 최대로 가능한 그룹의 합입니다. 이 값을 원소의 합에서 뺀 뒤 2를 곱하면 그룹의 합의 최소 차이를 구할 수 있습니다.

0개의 댓글