Skip to content

refactor: MaximumSumOfDistinctSubarraysWithLengthK #5433

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,55 +1,53 @@
package com.thealgorithms.others;

import java.util.HashSet;
import java.util.Set;

/*
References: https://en.wikipedia.org/wiki/Streaming_algorithm
* In this model, the function of interest is computing over a fixed-size window in the stream. As the stream progresses,
* items from the end of the window are removed from consideration while new items from the stream take their place.
* @author Swarga-codes (https://github.com/Swarga-codes)
*/
/**
* References: https://en.wikipedia.org/wiki/Streaming_algorithm
*
* This model involves computing the maximum sum of subarrays of a fixed size \( K \) from a stream of integers.
* As the stream progresses, elements from the end of the window are removed, and new elements from the stream are added.
*
* @author Swarga-codes (https://github.com/Swarga-codes)
*/
public final class MaximumSumOfDistinctSubarraysWithLengthK {
private MaximumSumOfDistinctSubarraysWithLengthK() {
}
/*
* Returns the maximum sum of subarray of size K consisting of distinct
* elements.
*
* @param k size of the subarray which should be considered from the given
* array.

/**
* Finds the maximum sum of a subarray of size K consisting of distinct elements.
*
* @param nums is the array from which we would be finding the required
* subarray.
* @param k The size of the subarray.
* @param nums The array from which subarrays will be considered.
*
* @return the maximum sum of distinct subarray of size K.
* @return The maximum sum of any distinct-element subarray of size K. If no such subarray exists, returns 0.
*/
public static long maximumSubarraySum(int k, int... nums) {
if (nums.length < k) {
return 0;
}
long max = 0; // this will store the max sum which will be our result
long s = 0; // this will store the sum of every k elements which can be used to compare with
// max
HashSet<Integer> set = new HashSet<>(); // this can be used to store unique elements in our subarray
// Looping through k elements to get the sum of first k elements
long masSum = 0; // Variable to store the maximum sum of distinct subarrays
long currentSum = 0; // Variable to store the sum of the current subarray
Set<Integer> currentSet = new HashSet<>(); // Set to track distinct elements in the current subarray

// Initialize the first window
for (int i = 0; i < k; i++) {
s += nums[i];
set.add(nums[i]);
currentSum += nums[i];
currentSet.add(nums[i]);
}
// Checking if the first kth subarray contains unique elements or not if so then
// we assign that to max
if (set.size() == k) {
max = s;
// If the first window contains distinct elements, update maxSum
if (currentSet.size() == k) {
masSum = currentSum;
}
// Looping through the rest of the array to find different subarrays and also
// utilising the sliding window algorithm to find the sum
// in O(n) time complexity
// Slide the window across the array
for (int i = 1; i < nums.length - k + 1; i++) {
s = s - nums[i - 1];
s = s + nums[i + k - 1];
// Update the sum by removing the element that is sliding out and adding the new element
currentSum = currentSum - nums[i - 1];
currentSum = currentSum + nums[i + k - 1];
int j = i;
boolean flag = false; // flag value which says that the subarray contains distinct elements
while (j < i + k && set.size() < k) {
while (j < i + k && currentSet.size() < k) {
if (nums[i - 1] == nums[j]) {
flag = true;
break;
Expand All @@ -58,17 +56,14 @@ public static long maximumSubarraySum(int k, int... nums) {
}
}
if (!flag) {
set.remove(nums[i - 1]);
currentSet.remove(nums[i - 1]);
}
set.add(nums[i + k - 1]);
// if the subarray contains distinct elements then we compare and update the max
// value
if (set.size() == k) {
if (max < s) {
max = s;
}
currentSet.add(nums[i + k - 1]);
// If the current window has distinct elements, compare and possibly update maxSum
if (currentSet.size() == k && masSum < currentSum) {
masSum = currentSum;
}
}
return max; // the final maximum sum
return masSum; // the final maximum sum
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,21 @@

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;
import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

public class MaximumSumOfDistinctSubarraysWithLengthKTest {
@Test
public void sampleTestCase1() {
assertEquals(15, MaximumSumOfDistinctSubarraysWithLengthK.maximumSubarraySum(3, 1, 5, 4, 2, 9, 9, 9));
}

@Test
public void sampleTestCase2() {
assertEquals(0, MaximumSumOfDistinctSubarraysWithLengthK.maximumSubarraySum(3, 4, 4, 4));
}

@Test
public void sampleTestCase3() {
assertEquals(12, MaximumSumOfDistinctSubarraysWithLengthK.maximumSubarraySum(3, 9, 9, 9, 1, 2, 3));
}

@Test
public void edgeCase1() {
assertEquals(0, MaximumSumOfDistinctSubarraysWithLengthK.maximumSubarraySum(0, 9, 9, 9));
@ParameterizedTest
@MethodSource("inputStream")
void testMaximumSubarraySum(int expected, int k, int[] arr) {
assertEquals(expected, MaximumSumOfDistinctSubarraysWithLengthK.maximumSubarraySum(k, arr));
}

@Test
public void edgeCase2() {
assertEquals(0, MaximumSumOfDistinctSubarraysWithLengthK.maximumSubarraySum(5, 9, 9, 9));
private static Stream<Arguments> inputStream() {
return Stream.of(Arguments.of(15, 3, new int[] {1, 5, 4, 2, 9, 9, 9}), Arguments.of(0, 3, new int[] {4, 4, 4}), Arguments.of(12, 3, new int[] {9, 9, 9, 1, 2, 3}), Arguments.of(0, 0, new int[] {9, 9, 9}), Arguments.of(0, 5, new int[] {9, 9, 9}), Arguments.of(9, 1, new int[] {9, 2, 3, 7}),
Arguments.of(15, 5, new int[] {1, 2, 3, 4, 5}), Arguments.of(6, 3, new int[] {-1, 2, 3, 1, -2, 4}), Arguments.of(10, 1, new int[] {10}), Arguments.of(0, 2, new int[] {7, 7, 7, 7}), Arguments.of(0, 3, new int[] {}), Arguments.of(0, 10, new int[] {1, 2, 3}));
}
}