From b890d4dd27641f66d1671be84eeee5a6581c4a8f Mon Sep 17 00:00:00 2001 From: Arya Singh Date: Mon, 14 Oct 2024 04:03:49 +0530 Subject: [PATCH 1/3] feat:Added Implementation of Split_Largest_Array_Sum Algorithm --- .../split_array_largest_sum.cpp | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 dynamic_programming/split_array_largest_sum.cpp diff --git a/dynamic_programming/split_array_largest_sum.cpp b/dynamic_programming/split_array_largest_sum.cpp new file mode 100644 index 00000000000..05c5774855a --- /dev/null +++ b/dynamic_programming/split_array_largest_sum.cpp @@ -0,0 +1,131 @@ +/** + * @file + * @brief Given an integer array nums and an integer k, split nums into k + * non-empty subarrays such that the largest sum of any subarray is minimized. + * Return the minimized largest sum of the split. + + * @details + * Example 1: + + * Input: nums = [7,2,5,10,8], k = 2 + * Output: 18 + * Explanation: There are four ways to split nums into two subarrays. + * The best way is to split it into [7,2,5] and [10,8], where the largest sum + * among the two subarrays is only 18. + + * Example 2: + + * Input: nums = [1,2,3,4,5], k = 2 + * Output: 9 + * Explanation: There are four ways to split nums into two subarrays. + * The best way is to split it into [1,2,3] and [4,5], where the largest sum + * among the two subarrays is only 9. + + * @author [ARYA PRATAP SINGH](https://github.com/ARYPROGRAMMER) + * [Leetcode](https://leetcode.com/problems/split-array-largest-sum/description/?envType=problem-list-v2&envId=dynamic-programming) + */ + +// header files +#include +#include +#include + +/** + * @namespace dynamic_programming + * @brief Dynamic Programming algorithms + */ +namespace dynamic_programming{ + /** + * @namespace split_array_largest_sum + * @brief split_array_largest_sum algorithm + */ + namespace split_array_largest_sum{ + + /** + * @brief This function calculates the minimum largest sum of the split + * @param nums integer array + * @param k integer + * @ + */ + + int dp[1003][53]; + + int f(int i, int j, vector& v) { + if (j < 0) { + if (i < 0) + return -1; + return INT_MAX; + } + if (i < 0) + return INT_MAX; + if (dp[i][j] != -1) + return dp[i][j]; + + int res = INT_MAX, sum = 0; + for (int k = i; k >= 0; k--) { + sum += v[k]; + res = min(res, max(sum, f(k - 1, j - 1, v))); + } + + return dp[i][j] = res; + } + + int splitArray(vector& nums, int k) { + memset(dp, -1, sizeof(dp)); + return f(nums.size() - 1, k - 1, nums); + } + } +} + +/** + * Test Function + * @return void + */ +static void test() { + // custom input vector + std::vector v{ + 7,2,5,10,8,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 + }; + // custom value of k + int k = 5; + + //calling the function + int ans = dynamic_programming::split_array_largest_sum::splitArray(v, k); + + // expected output + int expectedOutput = 30; + + // Testing implementation via assert function + // It will throw error if any of the expected test fails + // Else it will give nothing + assert(ans == expectedOutput); + + std::cout << "All tests passed successfully!\n"; + return; +} + +/** Main function (driver code)*/ +int main() { + // test for implementation + test(); + + // user input + int n; + std::cout << "Enter the number of elements in the array : "; + std::cin >> n; + std::vector v(n); + std::cout << "Enter the elements of the array : "; + for (int i = 0; i < n; i++) { + std::cin >> v[i]; + } + int k; + std::cout << "Enter the value of k : "; + std::cin >> k; + + int ans; + + // user output + ans = dynamic_programming::split_array_largest_sum::splitArray(v, k); + std::cout << "The minimum largest sum of the split is : " << ans << std::endl; + return 0; +} From b88773a212059b223398a675801223a2872610f9 Mon Sep 17 00:00:00 2001 From: Arya Pratap Singh <75311742+ARYPROGRAMMER@users.noreply.github.com> Date: Mon, 21 Oct 2024 18:59:34 +0530 Subject: [PATCH 2/3] Update split_array_largest_sum.cpp added necessary changes --- .../split_array_largest_sum.cpp | 185 +++++++++--------- 1 file changed, 95 insertions(+), 90 deletions(-) diff --git a/dynamic_programming/split_array_largest_sum.cpp b/dynamic_programming/split_array_largest_sum.cpp index 05c5774855a..1a89c04c8e5 100644 --- a/dynamic_programming/split_array_largest_sum.cpp +++ b/dynamic_programming/split_array_largest_sum.cpp @@ -1,131 +1,136 @@ /** * @file - * @brief Given an integer array nums and an integer k, split nums into k - * non-empty subarrays such that the largest sum of any subarray is minimized. - * Return the minimized largest sum of the split. - + * @brief [Split Array Largest Sum](https://leetcode.com/problems/split-array-largest-sum/) + * + * Given an integer array `nums` and an integer `k`, this program splits the + * array into `k` non-empty subarrays such that the largest sum of any subarray is minimized. + * This function returns the minimized largest sum of the split. + * * @details + * ### Problem Explanation: * Example 1: - - * Input: nums = [7,2,5,10,8], k = 2 - * Output: 18 - * Explanation: There are four ways to split nums into two subarrays. - * The best way is to split it into [7,2,5] and [10,8], where the largest sum - * among the two subarrays is only 18. - + * - Input: nums = [7,2,5,10,8], k = 2 + * - Output: 18 + * - Explanation: The best way to split it into two subarrays is [7,2,5] and [10,8], + * where the largest sum among the two subarrays is 18. + * * Example 2: - - * Input: nums = [1,2,3,4,5], k = 2 - * Output: 9 - * Explanation: There are four ways to split nums into two subarrays. - * The best way is to split it into [1,2,3] and [4,5], where the largest sum - * among the two subarrays is only 9. - - * @author [ARYA PRATAP SINGH](https://github.com/ARYPROGRAMMER) - * [Leetcode](https://leetcode.com/problems/split-array-largest-sum/description/?envType=problem-list-v2&envId=dynamic-programming) + * - Input: nums = [1,2,3,4,5], k = 2 + * - Output: 9 + * - Explanation: The best way to split it into two subarrays is [1,2,3] and [4,5], + * where the largest sum among the two subarrays is 9. + * + * ### Approach: + * Dynamic Programming is used to minimize the largest subarray sum by + * splitting the array into `k` subarrays. + * + * ### Time Complexity: + * O(n^2 * k), where `n` is the size of the array and `k` is the number of subarrays. + * + * ### Space Complexity: + * O(n * k), for the DP table. + * + * @author + * [ARYA PRATAP SINGH](https://github.com/ARYPROGRAMMER) */ -// header files #include -#include -#include +#include +#include +#include +#include -/** - * @namespace dynamic_programming - * @brief Dynamic Programming algorithms - */ -namespace dynamic_programming{ - /** - * @namespace split_array_largest_sum - * @brief split_array_largest_sum algorithm - */ - namespace split_array_largest_sum{ - - /** - * @brief This function calculates the minimum largest sum of the split - * @param nums integer array - * @param k integer - * @ - */ +namespace dynamic_programming { + namespace split_array_largest_sum { + // DP table for memoization int dp[1003][53]; - int f(int i, int j, vector& v) { - if (j < 0) { - if (i < 0) - return -1; - return INT_MAX; - } - if (i < 0) - return INT_MAX; - if (dp[i][j] != -1) - return dp[i][j]; + /** + * @brief Recursive function to calculate minimum largest sum of split + * @param i current index in the array + * @param j number of subarrays remaining + * @param v reference to input vector of numbers + * @return minimized largest sum for current split configuration + */ + int f(int i, int j, const std::vector &v) { + if (j < 0) return (i < 0) ? -1 : INT_MAX; + if (i < 0) return INT_MAX; + if (dp[i][j] != -1) return dp[i][j]; int res = INT_MAX, sum = 0; - for (int k = i; k >= 0; k--) { + for (int k = i; k >= 0; --k) { sum += v[k]; - res = min(res, max(sum, f(k - 1, j - 1, v))); + res = std::min(res, std::max(sum, f(k - 1, j - 1, v))); } - return dp[i][j] = res; - } + } - int splitArray(vector& nums, int k) { - memset(dp, -1, sizeof(dp)); + /** + * @brief Function to split array and find minimized largest sum + * @param nums vector of integers representing the array + * @param k number of subarrays + * @return minimized largest sum of any subarray after split + */ + int splitArray(const std::vector &nums, int k) { + std::memset(dp, -1, sizeof(dp)); return f(nums.size() - 1, k - 1, nums); } } } /** - * Test Function - * @return void + * @brief Test Function + * This function tests the `splitArray` function by using custom input. */ static void test() { - // custom input vector - std::vector v{ - 7,2,5,10,8,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 - }; - // custom value of k + std::vector test_array = {7, 2, 5, 10, 8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; int k = 5; - - //calling the function - int ans = dynamic_programming::split_array_largest_sum::splitArray(v, k); - - // expected output - int expectedOutput = 30; - // Testing implementation via assert function - // It will throw error if any of the expected test fails - // Else it will give nothing - assert(ans == expectedOutput); + // Calling the function + int result = dynamic_programming::split_array_largest_sum::splitArray(test_array, k); + + // Expected output + int expected = 30; + // Testing using assert + assert(result == expected); std::cout << "All tests passed successfully!\n"; - return; } -/** Main function (driver code)*/ -int main() { - // test for implementation - test(); - - // user input +/** + * @brief Function to handle user input and output. + * This function gathers input from the user and calls the `splitArray` function. + */ +void handleUserIO() { int n; - std::cout << "Enter the number of elements in the array : "; + std::cout << "Enter the number of elements in the array: "; std::cin >> n; - std::vector v(n); - std::cout << "Enter the elements of the array : "; - for (int i = 0; i < n; i++) { - std::cin >> v[i]; + + std::vector nums(n); + std::cout << "Enter the elements of the array: "; + for (int &num : nums) { + std::cin >> num; } + int k; - std::cout << "Enter the value of k : "; + std::cout << "Enter the value of k: "; std::cin >> k; - int ans; + int result = dynamic_programming::split_array_largest_sum::splitArray(nums, k); + std::cout << "The minimum largest sum of the split is: " << result << std::endl; +} + +/** + * @brief Main Function (driver code) + * This function calls test cases and handles user input/output. + */ +int main() { + // Running test cases + test(); + + // Handling user input/output + handleUserIO(); - // user output - ans = dynamic_programming::split_array_largest_sum::splitArray(v, k); - std::cout << "The minimum largest sum of the split is : " << ans << std::endl; return 0; } From 829fbbe429299893f81a66536f31cdb726fd09f5 Mon Sep 17 00:00:00 2001 From: Arya Pratap Singh <75311742+ARYPROGRAMMER@users.noreply.github.com> Date: Thu, 31 Oct 2024 12:01:15 +0530 Subject: [PATCH 3/3] Update split_array_largest_sum.cpp --- .../split_array_largest_sum.cpp | 246 ++++++++++-------- 1 file changed, 135 insertions(+), 111 deletions(-) diff --git a/dynamic_programming/split_array_largest_sum.cpp b/dynamic_programming/split_array_largest_sum.cpp index 1a89c04c8e5..9ea0d8cd84d 100644 --- a/dynamic_programming/split_array_largest_sum.cpp +++ b/dynamic_programming/split_array_largest_sum.cpp @@ -1,136 +1,160 @@ +// NOLINTBEGIN /** - * @file - * @brief [Split Array Largest Sum](https://leetcode.com/problems/split-array-largest-sum/) - * - * Given an integer array `nums` and an integer `k`, this program splits the - * array into `k` non-empty subarrays such that the largest sum of any subarray is minimized. - * This function returns the minimized largest sum of the split. - * - * @details - * ### Problem Explanation: - * Example 1: - * - Input: nums = [7,2,5,10,8], k = 2 - * - Output: 18 - * - Explanation: The best way to split it into two subarrays is [7,2,5] and [10,8], - * where the largest sum among the two subarrays is 18. - * - * Example 2: - * - Input: nums = [1,2,3,4,5], k = 2 - * - Output: 9 - * - Explanation: The best way to split it into two subarrays is [1,2,3] and [4,5], - * where the largest sum among the two subarrays is 9. - * - * ### Approach: - * Dynamic Programming is used to minimize the largest subarray sum by - * splitting the array into `k` subarrays. - * - * ### Time Complexity: - * O(n^2 * k), where `n` is the size of the array and `k` is the number of subarrays. - * - * ### Space Complexity: - * O(n * k), for the DP table. - * - * @author - * [ARYA PRATAP SINGH](https://github.com/ARYPROGRAMMER) + * @file split_array_largest_sum.cpp + * @brief Implementation of the Split Array Largest Sum problem + * @see https://leetcode.com/problems/split-array-largest-sum/ + * @author Original: ARYA PRATAP SINGH (https://github.com/ARYPROGRAMMER) + * + * Given an array of integers and an integer k, split the array into k non-empty + * contiguous subarrays such that the largest sum of any subarray is minimized. + * Returns the minimized largest sum of the split. + * + * @copyright Original implementation by ARYA PRATAP SINGH, modifications under project's license. */ +#include +#include +#include +#include #include #include -#include -#include -#include +/** + * @namespace dynamic_programming + * @brief Contains implementations of dynamic programming algorithms + */ namespace dynamic_programming { - namespace split_array_largest_sum { - - // DP table for memoization - int dp[1003][53]; - - /** - * @brief Recursive function to calculate minimum largest sum of split - * @param i current index in the array - * @param j number of subarrays remaining - * @param v reference to input vector of numbers - * @return minimized largest sum for current split configuration - */ - int f(int i, int j, const std::vector &v) { - if (j < 0) return (i < 0) ? -1 : INT_MAX; - if (i < 0) return INT_MAX; - if (dp[i][j] != -1) return dp[i][j]; - - int res = INT_MAX, sum = 0; - for (int k = i; k >= 0; --k) { - sum += v[k]; - res = std::min(res, std::max(sum, f(k - 1, j - 1, v))); - } - return dp[i][j] = res; + +/** + * @namespace split_array + * @brief Implementation of the Split Array Largest Sum problem and related utilities + */ +namespace split_array { + +// Constants for maximum array size and maximum number of splits +constexpr std::size_t MAX_ARRAY_SIZE = 1003; +constexpr std::size_t MAX_SPLITS = 53; + +/** + * @class SplitArraySolver + * @brief Class that implements the solution for the Split Array Largest Sum problem + */ +class SplitArraySolver { // NOLINT(cppcoreguidelines-special-member-functions) +private: + // DP table for memoization + std::array, MAX_ARRAY_SIZE> dp_{}; // NOLINT(misc-non-private-member-variables-in-classes) + + /** + * @brief Recursive helper function to calculate minimum largest sum of split + * @param i Current index in the array + * @param j Number of subarrays remaining + * @param nums Reference to input vector of numbers + * @return Minimized largest sum for current split configuration + */ + [[nodiscard]] int solve(const int i, const int j, + const std::vector& nums) noexcept { // NOLINT(misc-no-recursion) + if (j < 0) { + return (i < 0) ? -1 : INT_MAX; + } + if (i < 0) { + return INT_MAX; + } + if (dp_[i][j] != -1) { + return dp_[i][j]; } - /** - * @brief Function to split array and find minimized largest sum - * @param nums vector of integers representing the array - * @param k number of subarrays - * @return minimized largest sum of any subarray after split - */ - int splitArray(const std::vector &nums, int k) { - std::memset(dp, -1, sizeof(dp)); - return f(nums.size() - 1, k - 1, nums); + int result = INT_MAX; + int current_sum = 0; + + for (int k = i; k >= 0; --k) { + current_sum += nums[k]; + result = std::min(result, + std::max(current_sum, solve(k - 1, j - 1, nums))); } + + dp_[i][j] = result; + return result; } -} -/** - * @brief Test Function - * This function tests the `splitArray` function by using custom input. - */ -static void test() { - std::vector test_array = {7, 2, 5, 10, 8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; - int k = 5; - - // Calling the function - int result = dynamic_programming::split_array_largest_sum::splitArray(test_array, k); - - // Expected output - int expected = 30; - - // Testing using assert - assert(result == expected); - std::cout << "All tests passed successfully!\n"; -} +public: + /** + * @brief Constructor initializes the DP table + */ + SplitArraySolver() noexcept { + for (auto& row : dp_) { + row.fill(-1); + } + } + + /** + * @brief Splits array and finds minimized largest sum + * @param nums Vector of integers representing the array + * @param k Number of subarrays to split into + * @return Minimized largest sum of any subarray after split + * @throws std::invalid_argument if k is larger than the array size + */ + [[nodiscard]] int splitArray(const std::vector& nums, const int k) { + if (k > static_cast(nums.size())) { + throw std::invalid_argument("k cannot be larger than array size"); + } + + return solve(static_cast(nums.size()) - 1, k - 1, nums); + } +}; + +} // namespace split_array +} // namespace dynamic_programming /** - * @brief Function to handle user input and output. - * This function gathers input from the user and calls the `splitArray` function. + * @brief Test cases for the Split Array Largest Sum implementation */ -void handleUserIO() { - int n; - std::cout << "Enter the number of elements in the array: "; - std::cin >> n; - - std::vector nums(n); - std::cout << "Enter the elements of the array: "; - for (int &num : nums) { - std::cin >> num; +void runTests() { // NOLINT(misc-use-anonymous-namespace) + dynamic_programming::split_array::SplitArraySolver solver; + + // Test case 1: Basic case + { + const std::vector nums{7, 2, 5, 10, 8}; + assert(solver.splitArray(nums, 2) == 18); + } + + // Test case 2: Equal split + { + const std::vector nums{1, 2, 3, 4, 5}; + assert(solver.splitArray(nums, 2) == 9); } - int k; - std::cout << "Enter the value of k: "; - std::cin >> k; + // Test case 3: Larger array + { + const std::vector nums{7, 2, 5, 10, 8, 1, 2, 3, 4, 5}; + assert(solver.splitArray(nums, 3) == 18); + } - int result = dynamic_programming::split_array_largest_sum::splitArray(nums, k); - std::cout << "The minimum largest sum of the split is: " << result << std::endl; + // Test case 4: Edge case - k equals array size + { + const std::vector nums{1, 2, 3}; + assert(solver.splitArray(nums, 3) == 3); + } + + // Test case 5: Exception case + { + const std::vector nums{1, 2}; + try { + [[maybe_unused]] auto result = solver.splitArray(nums, 3); + assert(false); // Should not reach here + } catch (const std::invalid_argument&) { + // Expected exception + } + } + + std::cout << "All tests passed!\n"; } /** - * @brief Main Function (driver code) - * This function calls test cases and handles user input/output. + * @brief Main function runs the test suite + * @return 0 on successful execution */ int main() { - // Running test cases - test(); - - // Handling user input/output - handleUserIO(); - + runTests(); return 0; } +// NOLINTEND