Welcome to Subscribe On Youtube

2841. Maximum Sum of Almost Unique Subarray

Description

You are given an integer array nums and two positive integers m and k.

Return the maximum sum out of all almost unique subarrays of length k of nums. If no such subarray exists, return 0.

A subarray of nums is almost unique if it contains at least m distinct elements.

A subarray is a contiguous non-empty sequence of elements within an array.

 

Example 1:

Input: nums = [2,6,7,3,1,7], m = 3, k = 4
Output: 18
Explanation: There are 3 almost unique subarrays of size k = 4. These subarrays are [2, 6, 7, 3], [6, 7, 3, 1], and [7, 3, 1, 7]. Among these subarrays, the one with the maximum sum is [2, 6, 7, 3] which has a sum of 18.

Example 2:

Input: nums = [5,9,9,2,4,5,4], m = 1, k = 3
Output: 23
Explanation: There are 5 almost unique subarrays of size k. These subarrays are [5, 9, 9], [9, 9, 2], [9, 2, 4], [2, 4, 5], and [4, 5, 4]. Among these subarrays, the one with the maximum sum is [5, 9, 9] which has a sum of 23.

Example 3:

Input: nums = [1,2,1,2,1,2,1], m = 3, k = 3
Output: 0
Explanation: There are no subarrays of size k = 3 that contain at least m = 3 distinct elements in the given array [1,2,1,2,1,2,1]. Therefore, no almost unique subarrays exist, and the maximum sum is 0.

 

Constraints:

  • 1 <= nums.length <= 2 * 104
  • 1 <= m <= k <= nums.length
  • 1 <= nums[i] <= 109

Solutions

Solution 1: Sliding Window + Hash Table

We can traverse the array $nums$, maintain a window of size $k$, use a hash table $cnt$ to count the occurrence of each element in the window, and use a variable $s$ to sum all elements in the window. If the number of different elements in $cnt$ is greater than or equal to $m$, then we update the answer $ans = \max(ans, s)$.

After the traversal ends, return the answer.

The time complexity is $O(n)$, and the space complexity is $O(k)$. Here, $n$ is the length of the array.

  • class Solution {
        public long maxSum(List<Integer> nums, int m, int k) {
            Map<Integer, Integer> cnt = new HashMap<>();
            int n = nums.size();
            long s = 0;
            for (int i = 0; i < k; ++i) {
                cnt.merge(nums.get(i), 1, Integer::sum);
                s += nums.get(i);
            }
            long ans = 0;
            if (cnt.size() >= m) {
                ans = s;
            }
            for (int i = k; i < n; ++i) {
                cnt.merge(nums.get(i), 1, Integer::sum);
                if (cnt.merge(nums.get(i - k), -1, Integer::sum) == 0) {
                    cnt.remove(nums.get(i - k));
                }
                s += nums.get(i) - nums.get(i - k);
                if (cnt.size() >= m) {
                    ans = Math.max(ans, s);
                }
            }
            return ans;
        }
    }
    
  • class Solution {
    public:
        long long maxSum(vector<int>& nums, int m, int k) {
            unordered_map<int, int> cnt;
            long long s = 0;
            int n = nums.size();
            for (int i = 0; i < k; ++i) {
                cnt[nums[i]]++;
                s += nums[i];
            }
            long long ans = cnt.size() >= m ? s : 0;
            for (int i = k; i < n; ++i) {
                cnt[nums[i]]++;
                if (--cnt[nums[i - k]] == 0) {
                    cnt.erase(nums[i - k]);
                }
                s += nums[i] - nums[i - k];
                if (cnt.size() >= m) {
                    ans = max(ans, s);
                }
            }
            return ans;
        }
    };
    
  • class Solution:
        def maxSum(self, nums: List[int], m: int, k: int) -> int:
            cnt = Counter(nums[:k])
            s = sum(nums[:k])
            ans = 0
            if len(cnt) >= m:
                ans = s
            for i in range(k, len(nums)):
                cnt[nums[i]] += 1
                cnt[nums[i - k]] -= 1
                s += nums[i] - nums[i - k]
                if cnt[nums[i - k]] == 0:
                    cnt.pop(nums[i - k])
                if len(cnt) >= m:
                    ans = max(ans, s)
            return ans
    
    
  • func maxSum(nums []int, m int, k int) int64 {
    	cnt := map[int]int{}
    	var s int64
    	for _, x := range nums[:k] {
    		cnt[x]++
    		s += int64(x)
    	}
    	var ans int64
    	if len(cnt) >= m {
    		ans = s
    	}
    	for i := k; i < len(nums); i++ {
    		cnt[nums[i]]++
    		cnt[nums[i-k]]--
    		if cnt[nums[i-k]] == 0 {
    			delete(cnt, nums[i-k])
    		}
    		s += int64(nums[i]) - int64(nums[i-k])
    		if len(cnt) >= m {
    			ans = max(ans, s)
    		}
    	}
    	return ans
    }
    
  • function maxSum(nums: number[], m: number, k: number): number {
        const n = nums.length;
        const cnt: Map<number, number> = new Map();
        let s = 0;
        for (let i = 0; i < k; ++i) {
            cnt.set(nums[i], (cnt.get(nums[i]) || 0) + 1);
            s += nums[i];
        }
        let ans = cnt.size >= m ? s : 0;
        for (let i = k; i < n; ++i) {
            cnt.set(nums[i], (cnt.get(nums[i]) || 0) + 1);
            cnt.set(nums[i - k], cnt.get(nums[i - k])! - 1);
            if (cnt.get(nums[i - k]) === 0) {
                cnt.delete(nums[i - k]);
            }
            s += nums[i] - nums[i - k];
            if (cnt.size >= m) {
                ans = Math.max(ans, s);
            }
        }
        return ans;
    }
    
    
  • public class Solution {
        public long MaxSum(IList<int> nums, int m, int k) {
            Dictionary<int, int> cnt = new Dictionary<int, int>();
            int n = nums.Count;
            long s = 0;
            
            for (int i = 0; i < k; ++i) {
                if (!cnt.ContainsKey(nums[i])) {
                    cnt[nums[i]] = 1;
                }
                else {
                    cnt[nums[i]]++;
                }
                s += nums[i];
            }
            
            long ans = cnt.Count >= m ? s : 0;
            
            for (int i = k; i < n; ++i) {
                if (!cnt.ContainsKey(nums[i])) {
                    cnt[nums[i]] = 1;
                }
                else {
                    cnt[nums[i]]++;
                }
                if (cnt.ContainsKey(nums[i - k])) {
                    cnt[nums[i - k]]--;
                    if (cnt[nums[i - k]] == 0) {
                        cnt.Remove(nums[i - k]);
                    }
                }
                
                s += nums[i] - nums[i - k];
                
                if (cnt.Count >= m) {
                    ans = Math.Max(ans, s);
                }
            }
            
            return ans;
        }
    }
    

All Problems

All Solutions