문제
- 링크
- 배열
nums와 정수 k가 주어진다. 모든 값의 곱이 k보다 작은 subarray 개수를 구해야한다.
- 제약 조건
- 배열 길이:
1 <= nums.length <= 3 * 10^4
- 배열 값 범위:
1 <= nums[i] <= 1000
- k 범위:
0 <= k <= 10^6
풀이
풀기 전
- 처음에는 브루트포스로 모든 경우의 수를 계산해보려고 했다. 그러면 배열 길이를
n이라고 했을 때, subarray 개수는 총 n(n+1)/2개가 된다. n의 최대값이 30,000이므로, 약 4억 5천개..는 겨우 통과할 수도 있을 거 같은 값이라 애매했다.
- 사실 모든
subarray를 확인하는 건 최악의 경우이고, 만약 특정 subarray가 조건을 만족한다면 해당 subarray의 subarray도 조건을 만족한다는 걸 알 수 있다. 그래서 특정 인덱스에서 조건을 만족하는 가장 큰 subarray를 찾으면 된다. 처음에는 재귀로 풀려고 했는데 복잡해졌다. 그래서 discussion 참고해서 슬라이딩 윈도우 방식으로 풀었다.
코드
class Solution {
public int numSubarrayProductLessThanK(int[] nums, int k) {
int ans = 0;
int n = nums.length;
int left = 0, right = 0;
int val = 1;
while (right < n) {
val *= nums[right];
while (val >= k) {
if (left == right)
break;
val /= nums[left];
left++;
}
if (val < k)
ans += right - left + 1;
right++;
}
return ans;
}
}
- 예시
nums = [10,5,2,6], k = 100
left = 0, right = 0
val = 1 * nums[right] = 1 * 10 = 10
val < k 이므로 left 유지
ans += right - left + 1 => +1
right 이동
left = 0, right = 1
val = 10 * nums[right] = 10 * 5 = 50
val < k이므로 left 유지
ans += 1 - 0 + 1 => +2
right 이동
left = 0, right 2
val = 50 * nums[right] = 50 * 2 = 100
val >= k이므로 val /= nums[left] 해주면 100 / 10 = 10이고, left는 1 증가
ans += 2 - 1 + 1 => +2
right 이동
left = 1, right = 3
val = 10 * nums[right] = 10 * 6 = 60
val < k이므로 left 유지
ans += 3 - 1 + 1 => +3
right 이동
right가 배열 범위를 벗어나서 루프 종료
푼 후
앞에서 조건이 확인된 subarray는 뒤에서 다시 확인하지 않는다라는 아이디어가 중요한 거 같다. 그래서 새로 추가된 값에 대해서만 다시 subarray 조건을 체크할 수 있다.