diff --git a/DIRECTORY.md b/DIRECTORY.md index c7bc792d..b304ffee 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -59,6 +59,8 @@ * [Test Climb Stairs](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/climb_stairs/test_climb_stairs.py) * Countingbits * [Test Counting Bits](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/countingbits/test_counting_bits.py) + * Decodeways + * [Test Num Decodings](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/decodeways/test_num_decodings.py) * Domino Tromino Tiling * [Test Domino Tromino Tiling](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/dynamic_programming/domino_tromino_tiling/test_domino_tromino_tiling.py) * Duffle Bug Value @@ -214,6 +216,8 @@ * [Test Divide Chocolate](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/search/binary_search/divide_chocolate/test_divide_chocolate.py) * Maxruntime N Computers * [Test Max Runtime](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/search/binary_search/maxruntime_n_computers/test_max_runtime.py) + * Split Array Largest Sum + * [Test Split Array Largest Sum](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/search/binary_search/split_array_largest_sum/test_split_array_largest_sum.py) * [Test Binary Search](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/search/binary_search/test_binary_search.py) * Interpolation * [Test Interpolation Search](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/search/interpolation/test_interpolation_search.py) @@ -255,6 +259,8 @@ * Two Pointers * Array 3 Pointers * [Test Array 3 Pointers](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/two_pointers/array_3_pointers/test_array_3_pointers.py) + * Count Pairs + * [Test Count Pairs](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/two_pointers/count_pairs/test_count_pairs.py) * Find Sum Of Three * [Test Find Sum Of Three](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/two_pointers/find_sum_of_three/test_find_sum_of_three.py) * Merge Sorted Arrays diff --git a/algorithms/dynamic_programming/decodeways/README.md b/algorithms/dynamic_programming/decodeways/README.md new file mode 100644 index 00000000..372830c9 --- /dev/null +++ b/algorithms/dynamic_programming/decodeways/README.md @@ -0,0 +1,84 @@ +# Decode Ways + +You have intercepted a secret message encoded as a string of numbers. The message is decoded via the following mapping: + +```text +'1' -> "A" +'2' -> "B" +'3' -> "C" +... +'26' -> "Z" +``` +However, while decoding the message, you realize that there are many different ways you can decode the message because +some codes are contained in other codes ("2" and "5" vs "25"). + +For example, "11106" can be decoded into: + +- "AAJF" with the grouping (1, 1, 10, 6) +- "KJF" with the grouping (11, 10, 6) +- The grouping (1, 11, 06) is invalid because "06" is not a valid code (only "6" is valid). + +Note: there may be strings that are impossible to decode. + +Given a string s containing only digits, return the number of ways to decode it. If the entire string cannot be decoded +in any valid way, return 0. + +The test cases are generated so that the answer fits in a 32-bit integer. + +## Examples + +Example 1 + +```text +Input: s = "12" + +Output: 2 + +Explanation: + +"12" could be decoded as "AB" (1 2) or "L" (12). +``` + +Example 2 + +```text +Input: s = "226" + +Output: 3 + +Explanation: + +"226" could be decoded as "BZ" (2 26), "VF" (22 6), or "BBF" (2 2 6). +``` + +Example 3 + +```text +Input: s = "06" + +Output: 0 + +Explanation: + +"06" cannot be mapped to "F" because of the leading zero ("6" is different from "06"). In this case, the string is not +a valid encoding, so return 0. +``` + +Example 4 + +```text +s = 101 +output = 1 +Explanation: The only way to decode it is "JA". "01" cannot be decoded into "A" as "1" and "01" are different. +``` + +## Constraints + +- 1 <= s.length <= 100 +- s contains only digits and may contain leading zero(s). + +## Topics + +- String +- Dynamic Programming + diff --git a/algorithms/dynamic_programming/decodeways/__init__.py b/algorithms/dynamic_programming/decodeways/__init__.py new file mode 100644 index 00000000..20f7b9ca --- /dev/null +++ b/algorithms/dynamic_programming/decodeways/__init__.py @@ -0,0 +1,28 @@ +def num_decodings(s: str) -> int: + if not s or s[0] == "0": + return 0 + + n = len(s) + # Initialize the dp array. dp[i] will store the number of ways to decode the string s[:i] + dp = [0] * (n + 1) + dp[0] = 1 + dp[1] = 1 + + # Iterate through the string + for i in range(2, n + 1): + # Get the current character + current_char = s[i - 1] + # Get the previous character + prev_char = s[i - 2] + + # If the current character is not a zero, then we can decode it as a single character + if current_char != "0": + dp[i] += dp[i - 1] + + # If the previous character is 1 or 2 and the current character is less than or equal to 6, then we can decode + # it as a two character + if prev_char == "1" or (prev_char == "2" and current_char <= "6"): + dp[i] += dp[i - 2] + + # Return the number of ways to decode the string + return dp[n] diff --git a/algorithms/dynamic_programming/decodeways/test_num_decodings.py b/algorithms/dynamic_programming/decodeways/test_num_decodings.py new file mode 100644 index 00000000..8badd51e --- /dev/null +++ b/algorithms/dynamic_programming/decodeways/test_num_decodings.py @@ -0,0 +1,28 @@ +import unittest +from parameterized import parameterized +from algorithms.dynamic_programming.decodeways import num_decodings + +NUM_DECODINGS_TEST_CASES = [ + ("11106", 2), + ("12", 2), + ("226", 3), + ("06", 0), + ("101", 1), + ("12", 2), + ("012", 0), + ("0", 0), + ("30", 0), + ("10", 1), + ("27", 1), +] + + +class NumDecodingsTestCase(unittest.TestCase): + @parameterized.expand(NUM_DECODINGS_TEST_CASES) + def test_num_decodings(self, s: str, expected: int): + actual = num_decodings(s) + self.assertEqual(expected, actual) + + +if __name__ == "__main__": + unittest.main() diff --git a/algorithms/dynamic_programming/painthouse/test_min_cost_to_paint_houses.py b/algorithms/dynamic_programming/painthouse/test_min_cost_to_paint_houses.py index b097d8f6..a13a4fd6 100644 --- a/algorithms/dynamic_programming/painthouse/test_min_cost_to_paint_houses.py +++ b/algorithms/dynamic_programming/painthouse/test_min_cost_to_paint_houses.py @@ -1,7 +1,9 @@ import unittest from typing import List from parameterized import parameterized -from algorithms.dynamic_programming.painthouse import min_cost_to_paint_houses_alternate_colors +from algorithms.dynamic_programming.painthouse import ( + min_cost_to_paint_houses_alternate_colors, +) MIN_COST_PAINT_HOUSE = [ ([[8, 4, 15], [10, 7, 3], [6, 9, 12]], 13), @@ -16,5 +18,5 @@ def test_min_cost_to_paint_houses(self, cost: List[List[int]], expected: int): self.assertEqual(expected, actual) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/algorithms/search/binary_search/split_array_largest_sum/README.md b/algorithms/search/binary_search/split_array_largest_sum/README.md new file mode 100644 index 00000000..c00f5518 --- /dev/null +++ b/algorithms/search/binary_search/split_array_largest_sum/README.md @@ -0,0 +1,106 @@ +# Split Array Largest Sum + +Given an integer list nums and an integer k, split nums into k non-empty subarrays such that the largest sum among these +subarrays is minimized. The task is to find the minimized largest sum by choosing the split such that the largest sum of +every split of subarrays is the minimum among the sum of other splits. + +## Constraints + +- 1 <= nums.length <= 1000 +- 0 <= nums[i] <= 10^4 +- 1 <= k <= nums.length + +## Examples + +![Example 1](images/examples/split_array_largest_sum_example_1.png) +![Example 2](images/examples/split_array_largest_sum_example_2.png) +![Example 3](images/examples/split_array_largest_sum_example_3.png) +![Example 4](images/examples/split_array_largest_sum_example_4.png) + +## Topics + +- Array +- Binary Search +- Dynamic Programming +- Greedy +- Prefix Sum + +## Solution + +In a brute force method, you would try all possible ways to split the array into k subarrays, calculate the largest sum +for each split, and then find the smallest among those largest sums. This approach is extremely inefficient because the +number of ways to split the array grows exponentially as the size increases. + +We reverse the process by guessing a value for the minimum largest sum and checking if it’s feasible: + +- Instead of iterating through all splits, we only focus on testing whether a specific value allows us to split the + array into k subarrays. + +- But wait—just because one value works doesn’t mean it’s the smallest feasible value. We keep exploring smaller values + to achieve the most optimized result. + +The solution uses the binary search approach to find the optimal largest subarray sum without testing all possible splits. +The binary search finds the smallest possible value of the largest subarray sum and applies searching over the range of +possible values for this largest sum. But how do we guess this value? We guess the value using a certain range. +Here’s how: + +- **Left boundary**: The maximum element in the array is the minimum possible value for the largest subarray sum. This + is because any valid subarray must have a sum at least as large as the largest element. + +- **Right boundary**: The maximum possible value for the largest subarray sum is the sum of all elements in the array. + You would get this sum if the entire array were one single subarray. + +The binary search iteratively tests midpoints in the above ranges. It determines whether dividing the array results in +at most k subarrays will result in the smallest largest sum. If it does, the search shifts to lower values to minimize +the largest sum. Otherwise, it shifts to higher values. Still, there might be subarrays whose sum could be smaller, so +the search keeps going until the search range crosses each other, i.e., **left boundary** > **right boundary**. + +Here’s the step-by-step implementation of the solution: + +- Start by initializing the ranges for search. The left will be the largest number in the array, and the right will be + the sum of all numbers. +- Use a guessing approach. Start by considering a mid value between the left and right as a test value. +- Check if it is possible to divide the array into k subarrays so that the sum of no subarray is greater than mid. + - Start with an empty sum and add numbers from the array. If adding the next number exceeds mid: + - Start a new subarray with that number and increment the count of the subarrays. + - Return FALSE if the count exceeds k. Otherwise, return TRUE. +- Adjust the guessing range by checking if the number of subarrays needed is within the k and reduce the mid to see if + a smaller largest sum is possible. +- Otherwise, if the count of subarrays is more than k: + - Increase the mid to make larger groups possible. +- Continue adjusting the mid until left < right. Return left as it contains the minimized largest possible sum. + +- Let’s look at the following illustrations to get a better understanding of the solution: + +![Solution 1](images/solutions/split_array_largest_sum_solution_1.png) +![Solution 2](images/solutions/split_array_largest_sum_solution_2.png) +![Solution 3](images/solutions/split_array_largest_sum_solution_3.png) +![Solution 4](images/solutions/split_array_largest_sum_solution_4.png) +![Solution 5](images/solutions/split_array_largest_sum_solution_5.png) +![Solution 6](images/solutions/split_array_largest_sum_solution_6.png) +![Solution 7](images/solutions/split_array_largest_sum_solution_7.png) +![Solution 8](images/solutions/split_array_largest_sum_solution_8.png) +![Solution 9](images/solutions/split_array_largest_sum_solution_9.png) +![Solution 10](images/solutions/split_array_largest_sum_solution_10.png) +![Solution 11](images/solutions/split_array_largest_sum_solution_11.png) +![Solution 12](images/solutions/split_array_largest_sum_solution_12.png) +![Solution 13](images/solutions/split_array_largest_sum_solution_13.png) +![Solution 14](images/solutions/split_array_largest_sum_solution_14.png) +![Solution 15](images/solutions/split_array_largest_sum_solution_15.png) +![Solution 16](images/solutions/split_array_largest_sum_solution_16.png) +![Solution 17](images/solutions/split_array_largest_sum_solution_17.png) +![Solution 18](images/solutions/split_array_largest_sum_solution_18.png) +![Solution 19](images/solutions/split_array_largest_sum_solution_19.png) +![Solution 20](images/solutions/split_array_largest_sum_solution_20.png) + +### Time Complexity + +The time complexity of this solution is O(n log(m)), where n is the length of the input array, and m is the difference +between `max(nums)` and `sum(nums)` because the range of possible sums considered during the binary search is from +`max(nums)` to `sum(nums)`. This range size determines the number of iterations in the binary search. The tighter this +range, the fewer iterations are needed. However, in the worst case, it spans the full difference: `sum(nums) - max(nums)`. +The time complexity becomes `n log(m)` because the `can_split` function is called `n` times for each iteration. + +### Space Complexity + +The space complexity of this solution is O(1) because only constant space is used. diff --git a/algorithms/search/binary_search/split_array_largest_sum/__init__.py b/algorithms/search/binary_search/split_array_largest_sum/__init__.py new file mode 100644 index 00000000..974aa937 --- /dev/null +++ b/algorithms/search/binary_search/split_array_largest_sum/__init__.py @@ -0,0 +1,87 @@ +from typing import List + + +def split_array(nums: List[int], k: int) -> int: + if not nums: + return -1 + + left = max(nums) + right = sum(nums) + first_true_index = -1 + + def feasible(max_sum: int) -> bool: + """ + Check if we can split the array into at most k sub arrays with each sub array sum less than or equal to max_sum + """ + current_sum = 0 + # Start with one + sub_array_count = 1 + + for num in nums: + if current_sum + num > max_sum: + current_sum = num + sub_array_count += 1 + else: + current_sum += num + + return sub_array_count <= k + + while left <= right: + mid = (right + left) // 2 + if feasible(mid): + first_true_index = mid + # Find a smaller valid value + right = mid - 1 + else: + # Find a larger valid value + left = mid + 1 + + return first_true_index + + +def split_array_2(nums, k): + if not nums: + return -1 + + # Set the initial search range for the largest sum: + # Minimum is the largest number in the array, and maximum is the sum of all numbers + left, right = max(nums), sum(nums) + + def can_split(middle: int): + # Initialize the count of subarrays and the current sum of the current subarray + subarrays = 1 + current_sum = 0 + + for num in nums: + # Check if adding the current number exceeds the allowed sum (mid) + if current_sum + num > middle: + # Increment the count of subarrays + subarrays += 1 + # Start a new subarray with the current number + current_sum = num + + # If the number of subarrays exceeds the allowed k, return False + if subarrays > k: + return False + else: + # Otherwise, add the number to the current subarray + current_sum += num + + # Return True if the array can be split within the allowed subarray count + return True + + # Perform binary search to find the minimum largest sum + while left < right: + # Find the middle value of the current range + mid = (left + right) // 2 + + # Check if the array can be split into k or fewer subarrays with this maximum sum + if can_split(mid): + # If possible, try a smaller maximum sum + right = mid + else: + # Otherwise, increase the range to allow larger sums + left = mid + 1 + + # Return the smallest maximum sum that satisfies the condition + return left diff --git a/algorithms/search/binary_search/split_array_largest_sum/images/examples/split_array_largest_sum_example_1.png b/algorithms/search/binary_search/split_array_largest_sum/images/examples/split_array_largest_sum_example_1.png new file mode 100644 index 00000000..7c7cd2be Binary files /dev/null and b/algorithms/search/binary_search/split_array_largest_sum/images/examples/split_array_largest_sum_example_1.png differ diff --git a/algorithms/search/binary_search/split_array_largest_sum/images/examples/split_array_largest_sum_example_2.png b/algorithms/search/binary_search/split_array_largest_sum/images/examples/split_array_largest_sum_example_2.png new file mode 100644 index 00000000..896e20b3 Binary files /dev/null and b/algorithms/search/binary_search/split_array_largest_sum/images/examples/split_array_largest_sum_example_2.png differ diff --git a/algorithms/search/binary_search/split_array_largest_sum/images/examples/split_array_largest_sum_example_3.png b/algorithms/search/binary_search/split_array_largest_sum/images/examples/split_array_largest_sum_example_3.png new file mode 100644 index 00000000..aac92ead Binary files /dev/null and b/algorithms/search/binary_search/split_array_largest_sum/images/examples/split_array_largest_sum_example_3.png differ diff --git a/algorithms/search/binary_search/split_array_largest_sum/images/examples/split_array_largest_sum_example_4.png b/algorithms/search/binary_search/split_array_largest_sum/images/examples/split_array_largest_sum_example_4.png new file mode 100644 index 00000000..112dbed7 Binary files /dev/null and b/algorithms/search/binary_search/split_array_largest_sum/images/examples/split_array_largest_sum_example_4.png differ diff --git a/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_1.png b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_1.png new file mode 100644 index 00000000..bfe03f2f Binary files /dev/null and b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_1.png differ diff --git a/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_10.png b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_10.png new file mode 100644 index 00000000..f5137ebf Binary files /dev/null and b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_10.png differ diff --git a/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_11.png b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_11.png new file mode 100644 index 00000000..90066a80 Binary files /dev/null and b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_11.png differ diff --git a/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_12.png b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_12.png new file mode 100644 index 00000000..df27692d Binary files /dev/null and b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_12.png differ diff --git a/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_13.png b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_13.png new file mode 100644 index 00000000..228b207b Binary files /dev/null and b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_13.png differ diff --git a/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_14.png b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_14.png new file mode 100644 index 00000000..368fcf12 Binary files /dev/null and b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_14.png differ diff --git a/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_15.png b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_15.png new file mode 100644 index 00000000..6a95b079 Binary files /dev/null and b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_15.png differ diff --git a/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_16.png b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_16.png new file mode 100644 index 00000000..a5747b1f Binary files /dev/null and b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_16.png differ diff --git a/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_17.png b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_17.png new file mode 100644 index 00000000..e122bc78 Binary files /dev/null and b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_17.png differ diff --git a/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_18.png b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_18.png new file mode 100644 index 00000000..8dfda582 Binary files /dev/null and b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_18.png differ diff --git a/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_19.png b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_19.png new file mode 100644 index 00000000..2b1df267 Binary files /dev/null and b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_19.png differ diff --git a/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_2.png b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_2.png new file mode 100644 index 00000000..64b15b52 Binary files /dev/null and b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_2.png differ diff --git a/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_20.png b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_20.png new file mode 100644 index 00000000..771d5512 Binary files /dev/null and b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_20.png differ diff --git a/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_3.png b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_3.png new file mode 100644 index 00000000..8f96d383 Binary files /dev/null and b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_3.png differ diff --git a/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_4.png b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_4.png new file mode 100644 index 00000000..325488ee Binary files /dev/null and b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_4.png differ diff --git a/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_5.png b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_5.png new file mode 100644 index 00000000..ac232739 Binary files /dev/null and b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_5.png differ diff --git a/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_6.png b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_6.png new file mode 100644 index 00000000..3fdc86f5 Binary files /dev/null and b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_6.png differ diff --git a/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_7.png b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_7.png new file mode 100644 index 00000000..1db0696a Binary files /dev/null and b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_7.png differ diff --git a/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_8.png b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_8.png new file mode 100644 index 00000000..c675185c Binary files /dev/null and b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_8.png differ diff --git a/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_9.png b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_9.png new file mode 100644 index 00000000..5259ba95 Binary files /dev/null and b/algorithms/search/binary_search/split_array_largest_sum/images/solutions/split_array_largest_sum_solution_9.png differ diff --git a/algorithms/search/binary_search/split_array_largest_sum/test_split_array_largest_sum.py b/algorithms/search/binary_search/split_array_largest_sum/test_split_array_largest_sum.py new file mode 100644 index 00000000..b50de887 --- /dev/null +++ b/algorithms/search/binary_search/split_array_largest_sum/test_split_array_largest_sum.py @@ -0,0 +1,1042 @@ +import unittest +from typing import List +from parameterized import parameterized +from algorithms.search.binary_search.split_array_largest_sum import ( + split_array, + split_array_2, +) + +SPLIT_ARRAY_LARGEST_SUM_TEST_CASES = [ + ([1, 2, 3, 4, 5], 3, 6), + ([1, 2, 3, 4, 5], 2, 9), + ([5, 8, 2, 8, 3, 1], 1, 27), + ([1, 2, 3, 4, 5], 3, 6), + ([5, 8, 2, 8, 3, 1], 1, 27), + ([3, 4, 5, 4, 2], 4, 6), + ([3, 4, 3, 4, 5, 5, 8, 2], 4, 10), + ([7, 2, 5, 10, 8], 2, 18), + ([5, 2, 4], 2, 6), + ([1, 6, 2, 6, 8], 8, 8), + ( + [ + 205, + 7338, + 2958, + 1115, + 199, + 9189, + 8789, + 836, + 945, + 4477, + 2965, + 9855, + 8899, + 9020, + 8429, + 9396, + 8921, + 8866, + 2273, + 4671, + 8633, + 8133, + 2905, + 7687, + 4948, + 1614, + 6723, + 7300, + 4358, + 6217, + 9148, + 2805, + 8703, + 4542, + 2283, + 5241, + 1026, + 6524, + 3682, + 4138, + 7397, + 7726, + 7390, + 2829, + 5742, + 4467, + 3431, + 8410, + 300, + 8935, + 2631, + 4531, + 3189, + 8106, + 346, + 9486, + 9441, + 7647, + 8103, + 8876, + 5810, + 9231, + 232, + 7509, + 5396, + 6839, + 7161, + 2011, + 1309, + 2650, + 5933, + 351, + 4994, + 6355, + 3233, + 1045, + 5034, + 290, + 5300, + 7426, + 2514, + 2911, + 1681, + 3514, + 6794, + 1355, + 5325, + 6754, + 6330, + 3603, + 3094, + 3619, + 7707, + 9516, + 8377, + 9832, + 303, + 4143, + 3180, + 8058, + 7426, + 7475, + 2891, + 7597, + 9302, + 5036, + 1277, + 4340, + 5600, + 9170, + 9342, + 7342, + 9840, + 6184, + 5911, + 4335, + 5623, + 9001, + 3717, + 1247, + 4273, + 685, + 854, + 3363, + 3357, + 6986, + 6845, + 4412, + 1424, + 7086, + 3994, + 9699, + 5657, + 7992, + 9862, + 677, + 1345, + 1722, + 6942, + 6899, + 3741, + 9740, + 2943, + 663, + 5230, + 2885, + 1833, + 7635, + 5586, + 9840, + 2271, + 4508, + 6811, + 3070, + 1749, + 7711, + 4283, + 8633, + 473, + 6349, + 346, + 1605, + 4937, + 1943, + 3874, + 9300, + 592, + 2155, + 7704, + 3773, + 5617, + 9818, + 2175, + 7494, + 4729, + 6114, + 4832, + 4959, + 8260, + 8992, + 8341, + 8237, + 1123, + 6614, + 1060, + 8078, + 6432, + 9313, + 4984, + 2766, + 1562, + 3812, + 6061, + 9870, + 5401, + 235, + 4586, + 7867, + 6289, + 8799, + 5655, + 4072, + 5099, + 6807, + 958, + 5044, + 3805, + 2739, + 6156, + 5344, + 3048, + 6570, + 478, + 4007, + 3761, + 9926, + 6599, + 7156, + 6746, + 1362, + 3258, + 4989, + 5490, + 2394, + 4901, + 8658, + 868, + 6577, + 9274, + 8265, + 1457, + 1617, + 3361, + 508, + 8641, + 2481, + 1313, + 2510, + 3263, + 9630, + 6079, + 6813, + 4104, + 7269, + 4541, + 7588, + 4909, + 6186, + 2548, + 344, + 1880, + 5221, + 4452, + 3237, + 2396, + 7917, + 7004, + 8875, + 9453, + 2542, + 482, + 5828, + 9493, + 8023, + 5020, + 691, + 5206, + 348, + 3037, + 8988, + 5174, + 1364, + 2024, + 7646, + 6565, + 4156, + 4044, + 3793, + 172, + 1696, + 5781, + 1373, + 2128, + 9421, + 858, + 7822, + 3599, + 3966, + 6816, + 5115, + 8702, + 2885, + 8298, + 7366, + 1942, + 6369, + 7229, + 4717, + 3011, + 8435, + 253, + 9452, + 7163, + 7173, + 2558, + 5439, + 2732, + 1568, + 9809, + 1427, + 8951, + 4275, + 2846, + 4826, + 5387, + 2294, + 4684, + 2369, + 3550, + 6703, + 1139, + 1322, + 1469, + 4783, + 9186, + 501, + 947, + 3383, + 7240, + 1415, + 4835, + 747, + 531, + 5188, + 9709, + 4400, + 8306, + 7959, + 3348, + 2493, + 4025, + 8722, + 9167, + 1439, + 711, + 3106, + 9911, + 7079, + 8607, + 7233, + 1851, + 6161, + 2188, + 5777, + 3612, + 6502, + 8259, + 4878, + 5679, + 9922, + 591, + 3606, + 5363, + 5824, + 5169, + 9833, + 4481, + 9140, + 6820, + 3619, + 6067, + 9421, + 9932, + 5134, + 7634, + 9305, + 7871, + 511, + 5073, + 8015, + 6812, + 3580, + 541, + 2446, + 3937, + 3535, + 1121, + 643, + 1904, + 7099, + 9710, + 5162, + 9549, + 6181, + 3368, + 7653, + 7296, + 9383, + 4243, + 6362, + 4723, + 3638, + 6610, + 1892, + 7076, + 9549, + 6917, + 705, + 1931, + 7598, + 7706, + 6469, + 7367, + 4619, + 8113, + 6144, + 9128, + 9401, + 7317, + 5066, + 2588, + 7406, + 2699, + 9700, + 455, + 5908, + 1336, + 5283, + 120, + 554, + 3576, + 9943, + 9809, + 8760, + 5566, + 9055, + 1157, + 2315, + 1956, + 8066, + 9489, + 8779, + 2172, + 9398, + 3762, + 8945, + 1925, + 7707, + 1481, + 8064, + 4755, + 2558, + 2622, + 7440, + 7781, + 9149, + 1209, + 5410, + 1117, + 8296, + 9548, + 585, + 3038, + 4286, + 2153, + 742, + 1042, + 7788, + 6587, + 6858, + 1311, + 5486, + 3896, + 9350, + 3133, + 6643, + 3337, + 9848, + 4595, + 5218, + 3422, + 8473, + 9194, + 8759, + 5318, + 2153, + 1707, + 9659, + 602, + 8697, + 3889, + 6183, + 291, + 8879, + 4074, + 2933, + 6958, + 6825, + 7167, + 4491, + 8349, + 5738, + 1231, + 6635, + 1454, + 8959, + 9725, + 7137, + 6258, + 275, + 6092, + 4824, + 4649, + 8900, + 8212, + 3254, + 4107, + 8513, + 7773, + 297, + 4350, + 4877, + 3682, + 997, + 9830, + 3340, + 3506, + 6633, + 5607, + 1107, + 1404, + 2178, + 9681, + 3227, + 3693, + 8602, + 1968, + 3898, + 3480, + 7607, + 1476, + 845, + 9310, + 2210, + 3887, + 8348, + 2921, + 5845, + 5199, + 9084, + 661, + 2698, + 722, + 4060, + 5611, + 9443, + 5260, + 510, + 5263, + 9845, + 227, + 5094, + 9967, + 6666, + 4997, + 7266, + 7096, + 208, + 4501, + 1951, + 9127, + 5010, + 7854, + 3498, + 1373, + 9995, + 2330, + 9770, + 8429, + 9427, + 5215, + 8478, + 2962, + 1382, + 7440, + 8260, + 4832, + 2284, + 4714, + 1205, + 6938, + 46, + 5557, + 4459, + 8728, + 8354, + 8362, + 7086, + 3003, + 858, + 5303, + 6952, + 3785, + 4993, + 4760, + 4150, + 94, + 4679, + 3695, + 8053, + 8220, + 9398, + 9287, + 4301, + 2041, + 3599, + 9973, + 6009, + 6689, + 3799, + 9300, + 3090, + 2039, + 5780, + 1617, + 4622, + 7075, + 9849, + 3998, + 5095, + 1661, + 1769, + 72, + 3550, + 3277, + 1517, + 7739, + 1571, + 9828, + 5531, + 933, + 1472, + 9016, + 6741, + 4763, + 5576, + 3754, + 6893, + 7173, + 4800, + 4058, + 2705, + 3413, + 9224, + 53, + 7769, + 4367, + 1417, + 9647, + 3835, + 9058, + 5091, + 68, + 4573, + 7834, + 6686, + 3593, + 1296, + 7548, + 215, + 6176, + 7517, + 9926, + 2319, + 4923, + 6435, + 9131, + 6225, + 6420, + 9197, + 1826, + 2488, + 4387, + 8628, + 4553, + 9749, + 6573, + 8655, + 5353, + 9496, + 6491, + 6668, + 1231, + 1439, + 4712, + 7287, + 7352, + 5418, + 5673, + 4251, + 5557, + 2461, + 5516, + 1707, + 6186, + 2723, + 5604, + 7292, + 2791, + 5794, + 2055, + 3828, + 6046, + 8681, + 6386, + 7908, + 8760, + 556, + 6635, + 4, + 1095, + 6595, + 8083, + 1993, + 5568, + 2074, + 5502, + 8748, + 7628, + 2545, + 2690, + 529, + 7843, + 3227, + 7779, + 7238, + 4599, + 3149, + 1518, + 5001, + 2053, + 2225, + 9238, + 668, + 1826, + 1616, + 9974, + 449, + 9966, + 9800, + 6122, + 3904, + 2929, + 1201, + 2238, + 6268, + 609, + 601, + 3378, + 2648, + 5862, + 8104, + 9496, + 5153, + 6314, + 2926, + 2402, + 2619, + 2810, + 2429, + 942, + 2216, + 9950, + 9136, + 3316, + 5536, + 2841, + 6956, + 5859, + 369, + 5671, + 5628, + 8510, + 2, + 3268, + 599, + 8214, + 4522, + 289, + 5746, + 1003, + 1481, + 2377, + 4540, + 3040, + 4996, + 9267, + 5556, + 7117, + 6632, + 5305, + 6856, + 7913, + 3822, + 9940, + 1549, + 5009, + 1438, + 5652, + 1689, + 9380, + 3254, + 71, + 4753, + 2045, + 2972, + 8669, + 7043, + 6683, + 7499, + 8546, + 1659, + 6771, + 5346, + 2016, + 5704, + 3819, + 7906, + 4887, + 6974, + 4379, + 8019, + 3755, + 2390, + 3268, + 5164, + 8138, + 9751, + 816, + 472, + 660, + 3101, + 9770, + 9634, + 761, + 5452, + 6198, + 7139, + 8266, + 5045, + 6236, + 9348, + 8225, + 3687, + 8692, + 4647, + 7613, + 6166, + 3145, + 7115, + 2608, + 9083, + 8070, + 8067, + 1589, + 2331, + 7144, + 7190, + 3955, + 1539, + 5657, + 7988, + 4049, + 2156, + 2228, + 9506, + 6314, + 7094, + 3776, + 9192, + 2952, + 4484, + 2865, + 7480, + 6864, + 3194, + 7428, + 2063, + 5078, + 884, + 6767, + 4837, + 3478, + 1311, + 507, + 1330, + 6375, + 5040, + 2936, + 4778, + 4344, + 4098, + 8075, + 7920, + 1276, + 5721, + 3437, + 974, + 8637, + 4927, + 3257, + 8875, + 5530, + 5161, + 4818, + 4020, + 1860, + 3067, + 565, + 1195, + 798, + 5342, + 9389, + 7180, + 2607, + 4026, + 6214, + 7861, + 5033, + 9135, + 5060, + 5005, + 6197, + 8776, + 3725, + 2868, + 7082, + 2469, + 3787, + 2449, + 8339, + 6543, + 868, + 8766, + 7093, + 8036, + 574, + 5847, + 8317, + 9011, + 8274, + 9566, + 3983, + 3714, + 2332, + 1343, + 6609, + 4227, + 5739, + 8801, + 378, + 6449, + 7312, + 6192, + 3756, + 1739, + 1351, + 1750, + 1337, + 2061, + 4968, + 524, + 6372, + 9689, + 8094, + 9596, + 4747, + 5339, + 1551, + 1878, + 7637, + 5529, + 9314, + 6494, + 505, + 7012, + 9901, + 9840, + 2332, + 9939, + 790, + 108, + 5463, + 5009, + 246, + 6582, + 232, + 1973, + 9577, + 9798, + ], + 626, + 10917, + ), +] + + +class SplitArrayLargestSumTestCase(unittest.TestCase): + @parameterized.expand(SPLIT_ARRAY_LARGEST_SUM_TEST_CASES) + def test_split_array(self, nums: List[int], k: int, expected: int): + actual = split_array(nums, k) + self.assertEqual(expected, actual) + + @parameterized.expand(SPLIT_ARRAY_LARGEST_SUM_TEST_CASES) + def test_split_array_2(self, nums: List[int], k: int, expected: int): + actual = split_array_2(nums, k) + self.assertEqual(expected, actual) + + +if __name__ == "__main__": + unittest.main() diff --git a/algorithms/two_pointers/count_pairs/README.md b/algorithms/two_pointers/count_pairs/README.md new file mode 100644 index 00000000..615aea4f --- /dev/null +++ b/algorithms/two_pointers/count_pairs/README.md @@ -0,0 +1,85 @@ +# Count Pairs Whose Sum is Less than Target + +You are given a 0-indexed integer array, nums, of length n, and an integer target. Your task is to determine the number +of distinct pairs of indexes (i,j) such that: + +- 0≤i int: + """ + Counts the number of pairs of numbers in a list that sum to a value less than a target. + Uses a two-pointer approach to find the pairs, with a time complexity of O(n log n). + Modifies the list in place to sort the numbers. + Args: + nums (List[int]): A list of integers + target (int): The target value to search for + Returns: + int: The number of pairs of numbers in the list that sum to a value less than the target + """ + # Get the length of the numbers + n = len(nums) + + # Validation check, if there are less than 2 numbers, return 0. We can't form a pair here + if n < 2: + return 0 + + # Sort the nums in place, this incurs a time complexity of O(n log n) + nums.sort() + + # Initialize the left and right pointers + left, right = 0, n - 1 + + # Initialize the count of pairs + count = 0 + + # Use a while loop to find the pairs + while left < right: + # Get the current sum of the numbers at the left and right pointers + current_sum = nums[left] + nums[right] + # If the sum is less than the target, then the numbers in between the left and right pointers + # form valid pairs with the left pointer + if current_sum < target: + # Count the pairs + count += right - left + # Move the pointer up to find other distinct pairs + left += 1 + else: + # move the pointer down to find other pairs, reducing the sum of the boundary + right -= 1 + + # Return the count of pairs + return count diff --git a/algorithms/two_pointers/count_pairs/images/examples/count_pairs_example_1.png b/algorithms/two_pointers/count_pairs/images/examples/count_pairs_example_1.png new file mode 100644 index 00000000..6fbdfde9 Binary files /dev/null and b/algorithms/two_pointers/count_pairs/images/examples/count_pairs_example_1.png differ diff --git a/algorithms/two_pointers/count_pairs/images/examples/count_pairs_example_2.png b/algorithms/two_pointers/count_pairs/images/examples/count_pairs_example_2.png new file mode 100644 index 00000000..b47ec3a4 Binary files /dev/null and b/algorithms/two_pointers/count_pairs/images/examples/count_pairs_example_2.png differ diff --git a/algorithms/two_pointers/count_pairs/images/examples/count_pairs_example_3.png b/algorithms/two_pointers/count_pairs/images/examples/count_pairs_example_3.png new file mode 100644 index 00000000..9536f105 Binary files /dev/null and b/algorithms/two_pointers/count_pairs/images/examples/count_pairs_example_3.png differ diff --git a/algorithms/two_pointers/count_pairs/images/examples/count_pairs_example_4.png b/algorithms/two_pointers/count_pairs/images/examples/count_pairs_example_4.png new file mode 100644 index 00000000..367a1555 Binary files /dev/null and b/algorithms/two_pointers/count_pairs/images/examples/count_pairs_example_4.png differ diff --git a/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_1.png b/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_1.png new file mode 100644 index 00000000..42266466 Binary files /dev/null and b/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_1.png differ diff --git a/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_10.png b/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_10.png new file mode 100644 index 00000000..dd267209 Binary files /dev/null and b/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_10.png differ diff --git a/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_2.png b/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_2.png new file mode 100644 index 00000000..1c086dc2 Binary files /dev/null and b/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_2.png differ diff --git a/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_3.png b/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_3.png new file mode 100644 index 00000000..a9dc639c Binary files /dev/null and b/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_3.png differ diff --git a/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_4.png b/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_4.png new file mode 100644 index 00000000..c01cd38e Binary files /dev/null and b/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_4.png differ diff --git a/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_5.png b/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_5.png new file mode 100644 index 00000000..c44d9e26 Binary files /dev/null and b/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_5.png differ diff --git a/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_6.png b/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_6.png new file mode 100644 index 00000000..18ad713d Binary files /dev/null and b/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_6.png differ diff --git a/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_7.png b/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_7.png new file mode 100644 index 00000000..f2ecc538 Binary files /dev/null and b/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_7.png differ diff --git a/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_8.png b/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_8.png new file mode 100644 index 00000000..d207c1fd Binary files /dev/null and b/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_8.png differ diff --git a/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_9.png b/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_9.png new file mode 100644 index 00000000..5e547aba Binary files /dev/null and b/algorithms/two_pointers/count_pairs/images/solutions/count_pairs_solution_9.png differ diff --git a/algorithms/two_pointers/count_pairs/test_count_pairs.py b/algorithms/two_pointers/count_pairs/test_count_pairs.py new file mode 100644 index 00000000..d889ffa6 --- /dev/null +++ b/algorithms/two_pointers/count_pairs/test_count_pairs.py @@ -0,0 +1,27 @@ +import unittest +from typing import List +from parameterized import parameterized +from algorithms.two_pointers.count_pairs import count_pairs + + +COUNT_PAIRS_TEST_CASES = [ + ([1, 3, 2, 4, 5], 6, 4), + ([10, 20, 30, 40], 50, 2), + ([5, 1, 3, 2], 7, 4), + ([-1, 9, 17, 11, 6], 3, 0), + ([20, 20, 20, 20, 20, 20], 7, 0), + ([-5, -4, -3], -5, 3), + ([-1, 1, 2, 3, 1], 2, 3), + ([-6, 2, 5, -2, -7, -1, 3], -2, 10), +] + + +class CountPairsTestCase(unittest.TestCase): + @parameterized.expand(COUNT_PAIRS_TEST_CASES) + def test_count_pairs(self, nums: List[int], target: int, expected: int): + actual = count_pairs(nums, target) + self.assertEqual(expected, actual) + + +if __name__ == "__main__": + unittest.main() diff --git a/algorithms/two_pointers/two_sum_less_k/__init__.py b/algorithms/two_pointers/two_sum_less_k/__init__.py index 86dff9a3..6c7f0b19 100644 --- a/algorithms/two_pointers/two_sum_less_k/__init__.py +++ b/algorithms/two_pointers/two_sum_less_k/__init__.py @@ -8,7 +8,7 @@ def two_sum_less_than_k(nums: List[int], k: int) -> int: that is less than k. It takes the nums array and the target value k as input. Args: nums (List[int]): A sorted list of integers - k int: The target value to search for + k (int): The target value to search for Returns: The maximum sum of two elements that is less than k """ @@ -17,40 +17,38 @@ def two_sum_less_than_k(nums: List[int], k: int) -> int: # sort the numbers in ascending order to facilitate binary search nums.sort() + def search(target: int, start: int) -> int: + """ + Searches for a number that is less than the target in a sorted list of numbers. + Uses binary search to achieve a time complexity of O(log n) and find the index j such that the sum + nums[i]+nums[j] < k. It takes the nums array, target value, and the start range of the search as input. + Args: + target (int): The target value to search for + start (int): The starting index of the search range + Returns: + The index of the number that is less than the target, or -1 if no such number is found + """ + left, right = start, len(nums) - 1 + result = -1 + + while left <= right: + # calculate the midpoint of the search range + mid = (left + right) // 2 + if nums[mid] < target: + # update result to mid and move left to mid + 1 to look for larger values. + result = mid + left = mid + 1 + else: + # move right to mid - 1 to check smaller values. + right = mid - 1 + + return result + for x in range(len(nums)): # find the maximum sum of two elements that is less than k, with the first element being nums[x] - y = search(nums, k - nums[x], x + 1) + y = search(k - nums[x], x + 1) if y > x: # update max_sum with the maximum sum found so far max_sum = max(max_sum, nums[x] + nums[y]) return max_sum - - -def search(nums: List[int], target: int, start: int) -> int: - """ - Searches for a number that is less than the target in a sorted list of numbers. - Uses binary search to achieve a time complexity of O(log n) and find the index j such that the sum - nums[i]+nums[j] < k. It takes the nums array, target value, and the start range of the search as input. - Args: - nums (List[int]): A sorted list of integers - target int: The target value to search for - start int: The starting index of the search range - Returns: - The index of the number that is less than the target, or -1 if no such number is found - """ - left, right = start, len(nums) - 1 - result = -1 - - while left <= right: - # calculate the midpoint of the search range - mid = (left + right) // 2 - if nums[mid] < target: - # update result to mid and move left to mid + 1 to look for larger values. - result = mid - left = mid + 1 - else: - # move right to mid - 1 to check smaller values. - right = mid - 1 - - return result diff --git a/algorithms/two_pointers/two_sum_less_k/test_two_sum.py b/algorithms/two_pointers/two_sum_less_k/test_two_sum.py index 574ff9a6..51cc4f5b 100644 --- a/algorithms/two_pointers/two_sum_less_k/test_two_sum.py +++ b/algorithms/two_pointers/two_sum_less_k/test_two_sum.py @@ -1,48 +1,23 @@ import unittest -from . import two_sum_less_than_k +from typing import List +from parameterized import parameterized +from algorithms.two_pointers.two_sum_less_k import two_sum_less_than_k +TWO_SUM_LESS_K_TEST_CASES = [ + ([4, 2, 11, 2, 5, 3, 5, 8], 7, 6), + ([10, 20, 30], 15, -1), + ([34, 23, 1, 24, 75, 33, 54, 8], 60, 58), + ([5, 5, 5, 5, 5, 5], 15, 10), + ([1, 2, 3, 4, 5], 3, -1), +] -class TwoSumLessKTestCase(unittest.TestCase): - def test_1(self): - """numbers = [4,2,11,2,5,3,5,8], target = 7""" - numbers = [4, 2, 11, 2, 5, 3, 5, 8] - target = 7 - expected = 6 - actual = two_sum_less_than_k(numbers, target) - self.assertEqual(expected, actual) - def test_2(self): - """numbers = [10,20,30], target = 15""" - numbers = [10, 20, 30] - target = 15 - expected = -1 +class TwoSumLessKTestCase(unittest.TestCase): + @parameterized.expand(TWO_SUM_LESS_K_TEST_CASES) + def test_two_sum_less_k(self, numbers: List[int], target: int, expected: int): actual = two_sum_less_than_k(numbers, target) self.assertEqual(expected, actual) - def test_3(self): - """numbers = [34,23,1,24,75,33,54,8], k = 60""" - numbers = [34, 23, 1, 24, 75, 33, 54, 8] - k = 60 - expected = 58 - actual = two_sum_less_than_k(numbers, k) - self.assertEqual(expected, actual) - - def test_4(self): - """numbers = [5,5,5,5,5,5], k = 15""" - numbers = [5, 5, 5, 5, 5, 5] - k = 15 - expected = 10 - actual = two_sum_less_than_k(numbers, k) - self.assertEqual(expected, actual) - - def test_5(self): - """numbers = [1,2,3,4,5], k = 3""" - numbers = [1, 2, 3, 4, 5] - k = 3 - expected = -1 - actual = two_sum_less_than_k(numbers, k) - self.assertEqual(expected, actual) - if __name__ == "__main__": unittest.main()