Number of Unique Flavors After Sharing K Candies

Updated on 27 June, 2025
Number of Unique Flavors After Sharing K Candies header image

Problem Statement

In this problem, you are provided with an array candies where each element candies[i] corresponds to the flavor of the ith candy, indexed from 0. You are also tasked with a requirement from your mom to share exactly k consecutive candies with your little sister. Your goal is to determine how to do this such that the number of unique candy flavors you retain for yourself is maximized. The function needs to return the maximum number of distinct candy flavors that you can keep after fulfilling your mom's request of sharing k candies.

Examples

Example 1

Input:

candies = [1,2,2,3,4,3], k = 3

Output:

3

Explanation:

Give the candies in the range [1, 3] (inclusive) with flavors [2,2,3].
You can eat candies with flavors [1,4,3].
There are 3 unique flavors, so return 3.

Example 2

Input:

candies = [2,2,2,2,3,3], k = 2

Output:

2

Explanation:

Give the candies in the range [3, 4] (inclusive) with flavors [2,3].
You can eat candies with flavors [2,2,2,3].
There are 2 unique flavors, so return 2.
Note that you can also share the candies with flavors [2,2] and eat the candies with flavors [2,2,3,3].

Example 3

Input:

candies = [2,4,5], k = 0

Output:

3

Explanation:

You do not have to give any candies.
You can eat the candies with flavors [2,4,5].
There are 3 unique flavors, so return 3.

Constraints

  • 0 <= candies.length <= 105
  • 1 <= candies[i] <= 105
  • 0 <= k <= candies.length

Approach and Intuition

To solve this problem, we need to ensure that after giving away k consecutive candies, the candies that remain contain the maximum possible unique flavors. The challenge here revolves around ensuring that the subset of candy given away minimizes its impact on the variety of flavors left for yourself.

  1. Use Sliding Window Technique:

    • This technique helps in analyzing every possible sequence of k consecutive candies quickly.
    • As you slide the window of size k from the beginning to the end of the candy array, compute and adjust the flavors you are giving away.
  2. Maintain Two Sets or Frequency Counter:

    • Use one to track the flavors you are giving away in the current window.
    • Use another to keep track of all unique flavors. Each time you slide the window, update these sets respectively to reflect the change.
  3. Maximize Unique Flavors Kept:

    • The central logic involves maximizing the number of unique elements in the set that tracks flavors you’ve retained.
    • With each movement of the window, evaluate the difference between the total set of unique flavors and the set of flavors within the current window. The maximum of this calculated for each possible window position gives the desired result.
  4. Edge Case Consideration:

    • When k is 0, you give away no candies, thus you keep all flavors.
    • The edge cases where the candies array is empty should immediately return 0.

This approach leverages the sliding window technique effectively and ensures that each decision made maximizes the unique flavors retained, adhering correctly to any provided constraints.

Solutions

  • C++
  • Java
  • Python
cpp
class Solution {
public:
    int distributeCandies(vector<int>& candies, int windowSize) {
        int uniqueCount = 0;
    
        // Using a hash map to count frequency of each candy flavor
        unordered_map<int, int> flavorCount;
        for (int candy : candies) {
            if (++flavorCount[candy] == 1) {
                uniqueCount++;
            }
        }
    
        // Determine initially how many flavors are completely used
        int flavorsFullyUsed = 0;
        for (int i = 0; i < windowSize; i++) {
            if (--flavorCount[candies[i]] == 0) {
                flavorsFullyUsed++;
            }
        }
    
        // Compute initial max possible unique flavors outside the window
        int maxUniqueFlavors = uniqueCount - flavorsFullyUsed;
            
        // Slide over the remaining candies to update used flavors
        for (int i = windowSize; i < candies.size(); i++) {
            // Restore flavor count of the leaving candy
            if (++flavorCount[candies[i - windowSize]] == 1) {
                flavorsFullyUsed--;
            }
    
            // Decrement flavor count of the newly included candy
            if (--flavorCount[candies[i]] == 0) {
                flavorsFullyUsed++;
            }
            maxUniqueFlavors = max(maxUniqueFlavors, uniqueCount - flavorsFullyUsed);
        }
    
        return maxUniqueFlavors;
    }
};

The given C++ code implements a solution to find the maximum number of unique candy flavors that can be obtained after excluding exactly k candies from an input list of candies, where each candy is associated with a specific flavor.

  • The code starts by counting the frequency of each candy flavor using an unordered_map to store the count. This part of the code also tracks the total number of unique flavors.
  • After setting up the initial count of flavors, the code then processes the first windowSize (k) candies to simulate them being taken away. This adjustment allows the evaluation of how many flavors are left after these candies are removed.
  • Using a sliding window technique, the loop iterates through the candy list while updating the flavor counts as if windowSize candies are continuously being removed from the beginning of the remaining candies list and adjusting the counts accordingly.
  • The maximum number of unique flavors is updated at each step of the sliding window to ensure the highest possible number of unique flavors is identified.
  • Finally, the function returns the computed maximum unique flavors available after removing k candies.

This implementation efficiently calculates the number of unique flavors after exclusions using the sliding window and hash map, ensuring optimal performance over simply recalculating frequencies for each possible subset of size k. The approach minimizes the time spent recalculating the number of unique flavors for each possible selection of candies to remove.

java
import java.util.HashMap;
import java.util.Map;
    
class Solution {
    
    public int distributeCandies(int[] sweets, int num) {
        int distinctFlavors = 0;
    
        Map<Integer, Integer> flavorCount = new HashMap<>();
        for (int sweet : sweets) {
            flavorCount.put(sweet, flavorCount.getOrDefault(sweet, 0) + 1);
            if (flavorCount.get(sweet) == 1) {
                distinctFlavors++;
            }
        }
    
        int usedFlavors = 0;
        for (int j = 0; j < num; j++) {
            flavorCount.put(sweets[j], flavorCount.get(sweets[j]) - 1);
            if (flavorCount.get(sweets[j]) == 0) {
                usedFlavors++;
            }
        }
    
        int maxUniqueFlavors = distinctFlavors - usedFlavors;
    
        for (int i = num; i < sweets.length; i++) {
            flavorCount.put(sweets[i - num], flavorCount.get(sweets[i - num]) + 1);
            if (flavorCount.get(sweets[i - num]) == 1) {
                usedFlavors--;
            }
    
            flavorCount.put(sweets[i], flavorCount.get(sweets[i]) - 1);
            if (flavorCount.get(sweets[i]) == 0) {
                usedFlavors++;
            }
    
            maxUniqueFlavors = Math.max(maxUniqueFlavors, distinctFlavors - usedFlavors);
        }
    
        return maxUniqueFlavors;
    }
}

The provided Java solution addresses the problem of determining the maximum number of unique candy flavors that can be obtained after sharing a certain number (k) of candies. Here's how the algorithm works:

  1. Initialize distinctFlavors to keep track of the total number of unique flavors.
  2. Use a HashMap called flavorCount to count occurrences of each flavor in the sweets array.
  3. Count distinct flavors by iterating through the sweets array and updating the flavorCount map. Whenever a flavor is encountered for the first time (count == 1), increment the distinctFlavors.
  4. Initialize usedFlavors to zero, which will represent the reduction in distinct flavors due to sharing the first num candies.
  5. Decrease the count of each candy flavor in the first num range of the sweets array. If the count of any flavor becomes zero after decrement, increment usedFlavors.
  6. Calculate maxUniqueFlavors as distinctFlavors - usedFlavors, representing the initial count of unique flavors after the initial sharing.
  7. Slide through the sweets array beyond the initial num candies. For each candy i:
    • Increase the count of the flavor that leaves the window (i - num) and adjust usedFlavors if a flavor count increases from zero to one.
    • Decrease the count of the entering flavor and adjust usedFlavors if its count decreases to zero.
    • Update maxUniqueFlavors to capture the maximum number of unique flavors possible as the window slides.

The distributeCandies function finally returns maxUniqueFlavors, signifying the maximum number of unique candy flavors achievable after sharing k candies. The usage of the sliding window technique allows efficiently updating the count of distinct flavors as each new candy is considered in the range, and each candy exits the window.

python
class Solution:
    def distributeCandies(self, candies_list, num):
        # Store the frequency of each candy flavor.
        flavor_count = defaultdict(int)
        for candy in candies_list:
            flavor_count[candy] += 1
    
        # Count of distinct candy flavors.
        total_unique_flavors = len(flavor_count)
    
        # Count the flavors completely used in the initial block.
        depleted_flavors_count = 0
        for j in range(num):
            flavor_count[candies_list[j]] -= 1
            if flavor_count[candies_list[j]] == 0:
                depleted_flavors_count += 1
    
        # Calculate maximum distinct flavors possible after shifting the window.
        max_distinct = total_unique_flavors - depleted_flavors_count
    
        # Adjust window over the list of candies.
        for j in range(num, len(candies_list)):
            # Include candy going out of the window.
            flavor_count[candies_list[j - num]] += 1
            if flavor_count[candies_list[j - num]] == 1:
                depleted_flavors_count -= 1
    
            # Include new candy into the window.
            flavor_count[candies_list[j]] -= 1
            if flavor_count[candies_list[j]] == 0:
                depleted_flavors_count += 1
    
            # Recalculate the maximum distinct candy flavors.
            max_distinct = max(max_distinct, total_unique_flavors - depleted_flavors_count)
    
        return max_distinct

In this Python 3 solution, you determine the maximum number of unique candy flavors one can have after sharing exactly k candies. The approach involves using a sliding window combined with a dictionary for counting the occurrences of each flavor. Here's how the code operates:

  1. First, a dictionary flavor_count stores the frequency of each flavor present in the candies_list.

  2. You calculate the total number of unique flavors available, stored in total_unique_flavors.

  3. Then, iterate over the first num candies to determine how many flavors are completely used up in this segment, updating depleted_flavors_count.

  4. The potential maximum distinct flavors one can have after this initial distribution is then computed.

  5. Next, as you progress through the candies_list, adjust the window by one candy at a time. This involves:

    • Re-including the candy that exits the window and updating the flavor count.
    • Decreasing the count of the new candy entering the window and adjusting the depleted flavors if any flavor count reaches zero.
  6. After each adjustment, the maximum number of distinct flavors is recalculated using the current state of flavor depletion.

The function finally returns the maximum distinct flavors possible. This approach ensures efficient management and updating of candy distributions to optimize the variety of flavors.

Comments

No comments yet.