713.SubarrayProductLessThanK
Description:
Given an array of integers nums and an integer k, return the number of contiguous subarrays where the product of all the elements in the subarray is strictly less than k.
1 <= nums[i] <= 1000
Example 1:
Input: nums = [10,5,2,6], k = 100
Output: 8
Explanation: The 8 subarrays that have product less than 100 are:
[10], [5], [2], [6], [10, 5], [5, 2], [2, 6], [5, 2, 6]
Note that [10, 5, 2] is not included as the product of 100 is not strictly less than k.
Solution: Java Solution for Subarray Products Less Than K Problem
The above link introduces a solution with sliding window. Let's discuss about the summation formula: count += right - left + 1:
if current sliding window is [10, 5] and the cursor is moving to 2, 10 * 5 * 2 < 100, so the sliding window will become [10, 5, 2]. How many subarrays have been added now? [10,5,2] [5,2] and [2], we can imagine there are three people, and 2 handshake with 10 [10,5,2] and 5 [5,2] plus itself [2]. That's how many points there are in between right - left + 1.
fun numSubarrayProductLessThanK(nums: IntArray, k: Int): Int {
// since all number are positive,
// if we do not judge K <= 1, the product will always greater than k and left will move to out of array bound.
if (k <= 1) {
return 0
}
var product = 1
var left = 0
var result = 0
for (right in nums.indices) {
product *= nums[right]
// when product < k, the worst situation is left = right + 1, product = 1
while (product >= k) {
product /= nums[left]
left++
}
// calculate the subarrays number
result += right - left + 1
}
return result
}
2958.Length of Longest Subarray With at Most K Frequency
Description:
You are given an integer array nums and an integer k.
The frequency of an element x is the number of times it occurs in an array.
An array is called good if the frequency of each element in this array is less than or equal to k.
Return the length of the longest good subarray of nums .
A subarray is a contiguous non-empty sequence of elements within an array.
Example 1:
Input: nums = [1,2,3,1,2,3,1,2], k = 2
Output: 6
Explanation: The longest possible good subarray is [1,2,3,1,2,3] since the values 1, 2, and 3 occur at most twice in this subarray. Note that the subarrays [2,3,1,2,3,1] and [3,1,2,3,1,2] are also good.
It can be shown that there are no good subarrays with length more than 6.
We can use a sliding window to effciently keep track of the frequency of elements within a subarray.
Initialize two pointers, left and right, to mark the left and right boundaries of the current subarray. Then, Initialize a map to store the frequency of elements with in the current subarray. Moving right pointer until the number in right pointer has appeared more than k times. It's time for moving left pointer until the appear times of the number in right pointer drop into less than or equal k times. Update the maximum length of the good subbarry if necessary.
// sliding window (runtime Beats 86.36%)
fun maxSubarrayLength(nums: IntArray, k: Int): Int {
val map = mutableMapOf<Int, Int>()
var left = 0
var right = 0
var maxLength = 0
val n = nums.size
// end point
while (right < n) {
// record frequency of current number
map[nums[right]] = (map[nums[right]]?:0) + 1
// current right number is less than k, it is possible to have a longer length.
if (map[nums[right]]!! <= k) {
maxLength = max(maxLength, right - left + 1)
} else {
// move left point until right is less or equals k
while (map[nums[right]]!! > k) {
map[nums[left]] = map[nums[left]]!! - 1
left++
}
}
// move to next one
right++
}
return maxLength
}
2962.Count Subarrays Where Max Element Appears at Least K Times
Description:
You are given an integer array nums and a positive integer k.
Return the number of subarrays where the maximum element of nums appears at least k times in that subarray.
A subarray is a contiguous sequence of elements within an array.
Example 1:
Input: nums = [1,3,2,3,3], k = 2
Output: 6
Explanation: The subarrays that contain the element 3 at least 2 times are: [1,3,2,3], [1,3,2,3,3], [3,2,3], [3,2,3,3], [2,3,3] and [3,3].
Solution:
example: [1,3,2,3,3]
- Fist of all, we need to find out the max number of the list.(3)
- Then, we find the kth max number, [1,3,2,
3,3], and right point stop here. - In addition, we find the kth max number before right point,[1,3,2,
3,3], we let left point stop here. so use right and left point, we can calculate the subarrays is 2 (left point + 1, [1, 3, 2, 3] and [3, 2, 3]). - What's more, moving right point to the next, if the counts of max number are big than k, we move left point to the next max number.[1,3,2,3,
3]. Now, the number of added subarray is 4 (left + 1, [1,3,2,3,3], [3,2,3,3], [2,3,3], [3,3]). - In a nutshell, we just control the left and right point containing k max number, left point is the first max number and each time we move right point, the result add left + 1.
fun countSubarrays(nums: IntArray, k: Int): Long {
var max = nums[0]
// find max number
nums.forEach {
max = max(max, it)
}
var times = 0
var right = 0
var left = 0
var result = 0L
// end condition
while (right < nums.size) {
if (nums[right] == max) {
times++
}
// move right point to find next max number
if (times < k) {
right++
} else {
// current left to right contian k + 1 max number
if (times > k) {
left++
times--
}
// find the next max number
while (nums[left] != max) {
left++
}
// current left to right contain k max number,
// every index less and equal than left can form a good subarray.
result += left + 1
// move to next
right++
}
}
return result
}
992.Subarrays with K Different Integers
Descrption:
Given an integer array nums and an integer k, return the number of good subarrays of nums.
A good array is an array where the number of different integers in that array is exactly k.
- For example,
[1,2,3,1,2]has3different integers:1,2, and3.
A subarray is a contiguous part of an array.
Example 1:
Input: nums = [1,2,1,2,3], k = 2
Output: 7
Explanation: Subarrays formed with exactly 2 different integers: [1,2], [2,1], [1,2], [2,3], [1,2,1], [2,1,2], [1,2,1,2]
Solution: Editorial Solution
The offical answer is a really good method.
Here, we will learn the editorial solution approach 2. Let's take [1,2,1,2,3] and k = 2 as example. The most crucial part of the approach is that if there are duplicates of nums[left] within the current window, we need to keep shirinking the window from the left side until the frequency of nums[left] is zero. Because we need to maintain the correct count of distinct elements within the window. If we don't do this, then we can't decide how to move left point.
- left = 0, right = 0, subarray is [1], distinct number < 2, countine.
- left = 0, right = 1, subarray is [1,2], distinct number = 2, result = 0+1, countine.
- left = 0, right = 2, subarray is [1,2,1], distinct number = 2.
How should we move the point?first, move the left point, we do not want every nubmer in the subarray has multi counts. we want subarray like: [1,2,2,2,2,2], [1,2], no like: [1,2,2,1], [1,1,1,1,2,2,2]. So, we should move left point to 1, current subarray is [2,1], and counts contained in subarray is 1 (because, we have [2,1], we can make up a good subarray [1] + [2,1], what number does the contained have, then how many subarray it can form). continue - left = 1, right = 2, subarray is [2,1], contained count = 1, result += countainedCount([1,2,1]) + 1 ([2,1], the right point add the one). move right point.
- left = 1, right = 3, as the same as before, we should move left to next. and containedCount = 2 (1 and 2 [1,2,1,2,3]). and result += 2([1,2,
1,2], [2,1,2]) + 1([1,2]).
fun subarraysWithDistinct(nums: IntArray, k: Int): Int {
val length = nums.size
val windowNums = mutableMapOf<Int, Int>()
var result = 0
var left = 0
var right = 0
windowNums[nums[right]] = (windowNums[nums[right]]?:0) + 1
var numContainedFrontWindow = 0
while (right < length) {
if (windowNums.size < k) {
// distinct numbers less than k, move right point
right++
if (right < length) {
windowNums[nums[right]] = (windowNums[nums[right]] ?: 0) + 1
}
} else if (windowNums.size > k) {
// distinct numbers grate than k, move left point
windowNums[nums[left]] = windowNums[nums[left]]!! - 1
if (windowNums[nums[left]] == 0) {
windowNums.remove(nums[left])
}
left++
// new number is involved, the left point must be the only one in subarray.
// so, every subarray contain left point can't form a good subarray with the right point.
// reset the counter.
numContainedFrontWindow = 0
} else {
// distinct numbers equal k
if (windowNums[nums[left]]!! <= 1) {
// beyond left point, there is the only one
// each one can form a good subarray.
result += numContainedFrontWindow + 1
right++
if (right < length) {
windowNums[nums[right]] = (windowNums[nums[right]] ?: 0) + 1
}
} else {
// beyond left point, there are more same number as left point{the latest right point}.
numContainedFrontWindow++
windowNums[nums[left]] = windowNums[nums[left]]!! - 1
if (windowNums[nums[left]] == 0) {
windowNums.remove(nums[left])
}
left++
}
}
}
return result
}
2444.Count Subarrays With Fixed Bounds
You are given an integer array nums and two integers minK and maxK.
A fixed-bound subarray of nums is a subarray that satisfies the following conditions:
- The minimum value in the subarray is equal to
minK. - The maximum value in the subarray is equal to
maxK.
Return the number of fixed-bound subarrays.
A subarray is a contiguous part of an array.
Example 1:
Input: nums = [1,3,5,2,7,5], minK = 1, maxK = 5
Output: 2
Explanation: The fixed-bound subarrays are [1,3,5] and [1,3,5,2].
Example 2:
Input: nums = [1,1,1,1], minK = 1, maxK = 1
Output: 10
Explanation: Every subarray of nums is a fixed-bound subarray. There are 10 possible subarrays.
Solution: 98.43% Easy Solution with explanation
fun countSubarrays(nums: IntArray, minK: Int, maxK: Int): Long {
var res = 0L
var bad = -1
var left = -1
var right = -1
for (i in nums.indices) {
if (nums[i] !in minK..maxK) {
bad = i
}
if (nums[i] == minK) {
left = i
}
if (nums[i] == maxK) {
right = i
}
// if right < left, bad must > right
res += max(0, min(left, right) - bad)
}
return res
}