⚖️ 초보자 친화 가이드 'Minimum Removals to Balance Array' - 문제 3634 (C++, Python, JavaScript)

발행: (2026년 2월 6일 오전 10:43 GMT+9)
6 min read
원문: Dev.to

I’m happy to help translate the content, but I don’t see the text you’d like translated—only the source line is provided. Could you please paste the article or the specific text you want translated? Once I have the content, I’ll translate it into Korean while preserving the formatting and code blocks.

Problem Summary

You’re given:

  • An array of integers called nums.
  • An integer k representing the maximum allowed ratio between the largest and smallest elements.

Your goal is to calculate the minimum number of elements you need to remove to make the array balanced. An array is balanced if

[ \frac{\text{max}}{\text{min}} \le k ]

직관: 정렬의 힘

조건이 최소값과 최대값을 포함하도록 만족시키기 위해 첫 번째 단계는 배열을 정렬하는 것입니다. 정렬된 배열에서는 연속 부분 배열(슬라이스)의 첫 번째 요소가 최소값이 되고 마지막 요소가 최대값이 됩니다.

해결 방법은 탐욕적인 “두 포인터” 또는 “슬라이딩 윈도우” 접근법을 사용합니다.
하나의 요소를 최소값으로 고정하고 조건이 유지되는 한 가능한 많은 뒤의 요소들을 포함합니다. 정렬된 배열을 순회하면서, 인덱스 i에서 시작하는 “유효한 윈도우”를 추적합니다. 현재 요소 aA[i]를 기준으로 허용된 한도를 초과하면, i를 증가시켜 사실상 요소를 “제거”합니다. 우리는 최소 제거를 원하기 때문에, 유지할 수 있는 최대 요소 수를 찾는 것입니다.

단계별 설명: 예제 이해

예시: nums = [1, 6, 2, 9], k = 3

  1. 배열을 정렬 → [1, 2, 6, 9].
  2. i = 0 초기화.
  3. 반복:
    • a = 11 ≤ 1·3 → 윈도우 [1], i0 유지.
    • a = 22 ≤ 1·3 → 윈도우 [1, 2], i0 유지.
    • a = 66 > 1·3i1로 증가.
    • a = 9 → 새로운 최소값 2와 비교: 9 > 2·3i2로 증가.

최종 i 값은 2이며, 이는 균형 잡힌 배열을 만들기 위해 2개의 요소를 제거해야 함을 의미합니다.

코드 구현

C++

class Solution {
public:
    int minRemoval(vector<int>& A, int k) {
        // Sort to easily identify min and max in any range
        sort(A.begin(), A.end());
        int i = 0;
        for (int a : A) {
            // If current element is too large for the current min at A[i]
            // we increment i, effectively shrinking the 'kept' count
            if (a > 1LL * A[i] * k) {
                i++;
            }
        }
        return i;
    }
};

파이썬

class Solution:
    def minRemoval(self, nums: List[int], k: int) -> int:
        # Sort the numbers to maintain a sliding window of valid elements
        nums.sort()
        i = 0
        for a in nums:
            # If the current max (a) exceeds min (nums[i]) * k, we must remove an element
            if a > nums[i] * k:
                i += 1
        return i

자바스크립트

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var minRemoval = function(nums, k) {
    // Sort numerically as JS default sort is lexicographical
    nums.sort((a, b) => a - b);
    let i = 0;
    for (let a of nums) {
        // Check if the current element violates the balance condition
        if (a > nums[i] * k) {
            i++;
        }
    }
    return i;
};

주요 내용

  • 전처리로서 정렬: 문제에서 “최소”와 “최대” 제약이 언급될 때, 정렬을 하면 탐색 공간을 (O(n^2))에서 (O(n))으로 줄일 수 있습니다.
  • 슬라이딩 윈도우 로직: 포인터 i를 유지하면 유효 범위의 시작을 추적하고 그 범위 밖에 있는 요소가 몇 개인지 셀 수 있습니다.
  • 정수 오버플로: C++에서 두 큰 정수를 곱하면 int 한도를 초과할 수 있습니다. 1LL(long long)을 사용하면 곱셈을 안전하게 수행할 수 있습니다.

최종 생각

이 문제는 실제 시스템에서 “균형 잡힌” 상태가 어떻게 정의되는지를 보여줍니다. 서버의 로드 밸런싱이나 재무 포트폴리오 위험 관리에서 우리는 종종 단일 엔터티가 다른 엔터티보다 불균형하게 크게 되지 않도록 하여 시스템 고장이나 변동성을 방지해야 합니다. 이 슬라이딩‑윈도우 로직을 마스터하면 안전한 운영 매개변수 내에 머무는 시스템을 구축할 수 있습니다.

Back to Blog

관련 글

더 보기 »