Find X-Sum of All K-Long Subarrays II
HARDDescription
You are given an array nums of n integers and two integers k and x.
The x-sum of an array is calculated by the following procedure:
- Count the occurrences of all elements in the array.
- Keep only the occurrences of the top
xmost frequent elements. If two elements have the same number of occurrences, the element with the bigger value is considered more frequent. - Calculate the sum of the resulting array.
Note that if an array has less than x distinct elements, its x-sum is the sum of the array.
Return an integer array answer of length n - k + 1 where answer[i] is the x-sum of the subarray nums[i..i + k - 1].
Example 1:
Input: nums = [1,1,2,2,3,4,2,3], k = 6, x = 2
Output: [6,10,12]
Explanation:
- For subarray
[1, 1, 2, 2, 3, 4], only elements 1 and 2 will be kept in the resulting array. Hence,answer[0] = 1 + 1 + 2 + 2. - For subarray
[1, 2, 2, 3, 4, 2], only elements 2 and 4 will be kept in the resulting array. Hence,answer[1] = 2 + 2 + 2 + 4. Note that 4 is kept in the array since it is bigger than 3 and 1 which occur the same number of times. - For subarray
[2, 2, 3, 4, 2, 3], only elements 2 and 3 are kept in the resulting array. Hence,answer[2] = 2 + 2 + 2 + 3 + 3.
Example 2:
Input: nums = [3,8,7,8,7,5], k = 2, x = 2
Output: [11,15,15,15,12]
Explanation:
Since k == x, answer[i] is equal to the sum of the subarray nums[i..i + k - 1].
Constraints:
nums.length == n1 <= n <= 1051 <= nums[i] <= 1091 <= x <= k <= nums.length
Approaches
Checkout 2 different approaches to solve Find X-Sum of All K-Long Subarrays II. Click on different approaches to view the approach and algorithm in detail.
Brute Force Iteration
The most straightforward method is to iterate through each of the n - k + 1 possible subarrays of length k. For each subarray, we perform the full x-sum calculation from scratch. This involves counting element frequencies, sorting them according to the problem's criteria, identifying the top x elements, and summing their occurrences.
Algorithm
- Initialize an empty list
answerto store the results. - Iterate with a loop from
i = 0ton - kto represent the starting index of each subarray. - For each subarray
nums[i...i+k-1]:- Create a
HashMapto count the frequency of each element within this specific subarray. - Convert the
HashMapentries into aList. - Sort this list based on the specified criteria: primarily by frequency in descending order, and secondarily by element value in descending order for tie-breaking.
- Initialize a variable
currentXSumto zero. - Iterate through the top
min(x, list.size())elements of the sorted list. - For each of these top elements, add its total contribution (
value * frequency) tocurrentXSum. - Add
currentXSumto theanswerlist.
- Create a
- After the loop finishes, return the
answerarray.
We use a loop that iterates from i = 0 to n - k. In each iteration, i represents the starting index of a new subarray.
Inside the loop, for the subarray nums[i...i+k-1]:
- A
HashMapis used to store the frequency of each number in the currentk-length subarray. We iterate fromj = itoi+k-1to populate this map. - The entries of the frequency map are then transferred to a list.
- This list is sorted. The sorting criteria are: primarily by frequency in descending order, and secondarily by the element's value in descending order (for tie-breaking).
- We determine the number of top elements to consider, which is
min(x, number of distinct elements). - We iterate through these top elements, and for each one, we add
value * frequencyto a running sum for the current subarray. - This sum is the x-sum for the subarray starting at
i, and it's added to our final answer array.
This process is repeated for all n - k + 1 subarrays.
import java.util.*;
class Solution {
public long[] getXSum(int[] nums, int k, int x) {
int n = nums.length;
long[] answer = new long[n - k + 1];
for (int i = 0; i <= n - k; i++) {
Map<Integer, Integer> freqMap = new HashMap<>();
for (int j = i; j < i + k; j++) {
freqMap.put(nums[j], freqMap.getOrDefault(nums[j], 0) + 1);
}
List<Map.Entry<Integer, Integer>> entries = new ArrayList<>(freqMap.entrySet());
entries.sort((a, b) -> {
if (!a.getValue().equals(b.getValue())) {
return b.getValue().compareTo(a.getValue());
}
return b.getKey().compareTo(a.getKey());
});
long currentXSum = 0;
for (int j = 0; j < Math.min(x, entries.size()); j++) {
Map.Entry<Integer, Integer> entry = entries.get(j);
currentXSum += (long) entry.getKey() * entry.getValue();
}
answer[i] = currentXSum;
}
return answer;
}
}
Complexity Analysis
Pros and Cons
- Simple to understand and implement.
- Correct for all cases, assuming no time constraints.
- Highly inefficient due to redundant computations for overlapping parts of subarrays.
- Will likely result in a 'Time Limit Exceeded' error for large inputs as specified in the constraints.
Code Solutions
Checking out 3 solutions in different languages for Find X-Sum of All K-Long Subarrays II. Click on different languages to view the code.
class Solution { private TreeSet < int []> l = new TreeSet <>(( a , b ) -> a [ 0 ] == b [ 0 ] ? a [ 1 ] - b [ 1 ] : a [ 0 ] - b [ 0 ]); private TreeSet < int []> r = new TreeSet <>( l . comparator ()); private Map < Integer , Integer > cnt = new HashMap <>(); private long s ; public long [] findXSum ( int [] nums , int k , int x ) { int n = nums . length ; long [] ans = new long [ n - k + 1 ]; for ( int i = 0 ; i < n ; ++ i ) { int v = nums [ i ]; remove ( v ); cnt . merge ( v , 1 , Integer: : sum ); add ( v ); int j = i - k + 1 ; if ( j < 0 ) { continue ; } while (! r . isEmpty () && l . size () < x ) { var p = r . pollLast (); s += 1L * p [ 0 ] * p [ 1 ]; l . add ( p ); } while ( l . size () > x ) { var p = l . pollFirst (); s -= 1L * p [ 0 ] * p [ 1 ]; r . add ( p ); } ans [ j ] = s ; remove ( nums [ j ]); cnt . merge ( nums [ j ], - 1 , Integer: : sum ); add ( nums [ j ]); } return ans ; } private void remove ( int v ) { if (! cnt . containsKey ( v )) { return ; } var p = new int [] { cnt . get ( v ), v }; if ( l . contains ( p )) { l . remove ( p ); s -= 1L * p [ 0 ] * p [ 1 ]; } else { r . remove ( p ); } } private void add ( int v ) { if (! cnt . containsKey ( v )) { return ; } var p = new int [] { cnt . get ( v ), v }; if (! l . isEmpty () && l . comparator (). compare ( l . first (), p ) < 0 ) { l . add ( p ); s += 1L * p [ 0 ] * p [ 1 ]; } else { r . add ( p ); } } }Video Solution
Watch the video walkthrough for Find X-Sum of All K-Long Subarrays II
Similar Questions
5 related questions you might find useful
Patterns:
Data Structures:
Subscribe to Scale Engineer newsletter
Learn about System Design, Software Engineering, and interview experiences every week.
No spam, unsubscribe at any time.