Leetcode 2226. Maximum Candies Allocated to K Children

#Array #Binary Search

Table of Contents

Problem Informations

Problem Description

You are given a 0-indexed integer array candies. Each element in the array denotes a pile of candies of size $candies[i]$. You can divide each pile into any number of sub piles, but you cannot merge two piles together.

You are also given an integer $k$. You should allocate piles of candies to $k$ children such that each child gets the same number of candies. Each child can be allocated candies from only one pile of candies and some piles of candies may go unused.

Return the maximum number of candies each child can get.

Example 1:

Input: candies = [5,8,6], k = 3
Output: 5
Explanation: We can divide candies[1] into 2 piles of size 5 and 3, and candies[2] into 2 piles of size 5 and 1. We now have five piles of candies of sizes 5, 5, 3, 5, and 1. We can allocate the 3 piles of size 5 to 3 children. It can be proven that each child cannot receive more than 5 candies.

Example 2:

Input: candies = [2,5], k = 11
Output: 0
Explanation: There are 11 children but only 7 candies in total, so it is impossible to ensure each child receives at least one candy. Thus, each child gets no candy and the answer is 0.

Constraints:

  • $1 \leq candies.length \leq 10^5$
  • $1 \leq candies[i] \leq 10^7$
  • $1 \leq k \leq 10^{12}$

Intuition

The problem requires determining the maximum number of candies that each child can receive given the constraints on pile division. The fundamental challenge involves ensuring that exactly $k$ children receive the same number of candies, each from a single pile that can be subdivided but not merged with others. The optimal approach involves binary search on the possible number of candies each child can receive, leveraging the insight that if $t$ candies per child is feasible, fewer candies per child will also be feasible, and if it’s not feasible, more candies will not be either.

Approach

The primary approach is to apply a binary search technique over the possible values for candies each child could potentially receive. Here are the detailed steps:

  1. Function check: This helper function determines if it is possible to distribute at least $t$ candies to each child from the given pile configuration. The function traverses each pile of candies, calculates how many children can receive $t$ candies from each pile by integer division, and subtracts this from $k$. If all $k$ children can be satisfied in this manner, the function returns true. The edge case where $t = 0$ immediately returns false because no candies can be distributed.

  2. Determine Jump Sizes: Start by setting the initial jump size to the size of the largest pile of candies, which represents the upper bound of possible candies one child could potentially receive if that pile were to be dedicated to a single child.

  3. Binary Search with Decaying Step Size:

    • Initialize ans to zero, which will ultimately hold the maximum possible candies each child can receive.
    • Perform a loop where, for each given jump size, check if it is possible to distribute ans + jump candies to each child using the check function.
    • If the condition is satisfied, increment ans by the current jump size, effectively increasing the lower bound and searching for a higher feasible distribution.
    • Divide the jump size by 2 in each iteration for gradually finer exploration until the precision reaches 1, which ensures that the result converges to the maximum feasible value.
  4. Returning the Result: After the loop ends, ans will contain the largest number of candies that can be distributed to each child under the given constraints, which is then returned as the solution.

This method efficiently finds the solution using logarithmic search space reduction combined with greedy distribution checks within each step, adhering to the constraints and ensuring an optimal solution within the provided limits.

Code

C++

class Solution {
public:
    // Function to check if it is possible to distribute candies such that each child gets exactly 't' candies
    bool check(vector<int>& candies, long long k, int t) {
        if (t == 0) return false; // If no candies per child, return false
        for (int c : candies) {
            k -= c / t; // Reduce the required number of children by the number of children one pile can satisfy
        }
        return (k <= 0); // Return true if all children can be satisfied
    }
    
    // Function to find the maximum number of candies each child can get
    int maximumCandies(vector<int>& candies, long long k) {
        int ans = 0; // Initialize answer to zero
        // Determine initial jump size based on the largest pile of candies
        for (int jump = *max_element(candies.begin(), candies.end()); jump > 0; jump /= 2) {
            // Increase ans by jump as long as it is possible to distribute candies with ans + jump
            while (check(candies, k, ans + jump)) {
                ans += jump;
            }
        }
        return ans; // Return the maximum number of candies each child can get
    }
};

Python

class Solution:
    # Function to check if it is possible to distribute candies such that each child gets exactly 't' candies
    def check(self, candies, k, t):
        if t == 0:
            return False  # If no candies per child, return false
        for c in candies:
            k -= c // t  # Reduce the required number of children by the number of children one pile can satisfy
        return k <= 0  # Return true if all children can be satisfied

    # Function to find the maximum number of candies each child can get
    def maximumCandies(self, candies, k):
        ans = 0  # Initialize answer to zero
        # Determine initial jump size based on the largest pile of candies
        jump = max(candies)
        while jump > 0:
            # Increase ans by jump as long as it is possible to distribute candies with ans + jump
            while self.check(candies, k, ans + jump):
                ans += jump
            jump //= 2
        return ans  # Return the maximum number of candies each child can get

Complexity

  • Time complexity: $O(n \log m)$

    The maximumCandies function iterates through different jump sizes starting from the largest pile of candies and reduces the jump size by half in each iteration. This process essentially simulates a binary search over the range of possible numbers of candies each child can receive. The maximum number of candies that can be given to a child is determined by the largest pile, which is denoted as $m = \max(\text{candies})$. Therefore, the binary search runs for $O(\log m)$ iterations.

    For each iteration in the binary search, the function check is called, which runs in $O(n)$ time complexity where $n$ is the number of piles, since it iterates through the candies array to compute if the distribution is possible.

    Combining these, the overall time complexity is $O(n \log m)$.

  • Space complexity: $O(1)$

    The space complexity is constant, $O(1)$, because the algorithm uses only a fixed amount of extra space beyond the input list and the parameters. The function does not allocate additional data structures whose size grows with the input. Thus, only a constant amount of space is used regardless of the size of the input.

Disclaimer: All reference materials on this website are sourced from the internet and are intended for learning purposes only. If you believe any content infringes upon your rights, please contact me at csnote.cc@gmail.com, and I will remove the relevant content promptly.


Feedback Welcome: If you notice any errors or areas for improvement in the articles, I warmly welcome your feedback and corrections. Your input will help this blog provide better learning resources. This is an ongoing process of learning and improvement, and your suggestions are valuable to me. You can reach me at csnote.cc@gmail.com.