https://leetcode.com/problems/subarray-sums-divisible-by-k/description/
Subarray Sums Divisible by K - LeetCode
Can you solve this real interview question? Subarray Sums Divisible by K - Given an integer array nums and an integer k, return the number of non-empty subarrays that have a sum divisible by k. A subarray is a contiguous part of an array. Example 1: Inp
leetcode.com
이 문제는 구간합 % K 가 0 이되는 구간을 모두 구하는 문제입니다.
이 문제는 배열 내에 음수가 존재하기 때문에 슬라이딩 윈도우로 구간합을 구하기 충분하지 않습니다.
그래서 다른 방식을 이용해서 문제를 해결해야 합니다.

문제를 다시 정의해보면,
Sum(i)를 0번 인덱스부터 i번 인덱스까지의 누적합이라고 할 때,
우리가 구해야 하는 것은 다음 조건을 만족하는 (i, j) 쌍의 개수입니다.
(Sum(i) - Sum(j)) % k == 0
여기서 Sum(i) - Sum(j)는 결국 어떤 구간의 합을 의미하므로,
이 문제는 곧 합이 k로 나누어떨어지는 부분 배열의 개수를 구하는 문제라고 볼 수 있습니다.
처음에는 Prefix Sum을 구한 뒤, 모든 (i, j) 쌍을 이중 반복문으로 확인할 수도 있습니다.
하지만 배열의 길이가 최대 3 * 10^4이므로, 이런 방식은 O(n^2)가 되어 비효율적입니다.
그래서 식을 다시 보면,
(Sum(i) - Sum(j)) % k == 0
이라는 조건은 곧
Sum(i) % k == Sum(j) % k
와 동치입니다.
즉, 두 누적합을 k로 나눈 나머지가 같다면,
그 사이 구간의 합은 k로 나누어떨어집니다.
따라서 배열을 왼쪽부터 순회하면서 현재까지의 누적합 Sum(i)를 구하고,
이 값을 k로 나눈 나머지를 계산합니다.
그다음, 이전까지 등장했던 누적합 나머지 값들 중 현재와 같은 값의 개수만큼
조건을 만족하는 부분 배열이 새롭게 만들어집니다.
이를 위해 Map을 사용해
각 나머지 값이 몇 번 등장했는지를 저장합니다.
- Key: Sum % k
- Value: 해당 나머지가 나온 횟수
정리하면 알고리즘은 다음과 같습니다.
- 배열을 순회하며 누적합을 구한다.
- 현재 누적합을 k로 나눈 나머지를 구한다.
- 이전에 같은 나머지가 몇 번 나왔는지 확인한다.
- 그 개수를 정답에 더한다.
- 현재 나머지의 등장 횟수를 Map에 기록한다.
코드
class Solution {
public int subarraysDivByK(int[] nums, int k) {
Map<Integer,Integer> map = new HashMap<>();
int sum = 0;
int ans = 0;
for(int x : nums){
sum += x;
int curK = ((sum % k) + k) % k;
if(curK == 0) ans++;
if(map.containsKey(curK)) ans += map.get(curK);
map.put(curK, map.getOrDefault(curK,0) + 1);
}
return ans;
}
}
'알고리즘 > LeetCode' 카테고리의 다른 글
| 3666. Minimum Operations to Equalize Binary String (0) | 2026.03.05 |
|---|---|
| 1727. Largest Submatrix With Rearrangements - Java (1) | 2023.11.26 |