-
Notifications
You must be signed in to change notification settings - Fork 2
feat(algorithms, two-pointers, dynamic-programming): two-pointers dp and bs problems #154
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
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
8c55e90
feat(algorithms, dynamic-programming): decode ways
BrianLusina df417c2
feat(algorithms, binary-search): split array largest sum
BrianLusina a2071a2
updating DIRECTORY.md
933cc3c
feat(algorithms, two-pointers): count pairs
BrianLusina 58b252a
updating DIRECTORY.md
81693fe
refactor(algorithms, binary-search): split array - guard check for em…
BrianLusina 93845d3
Update algorithms/search/binary_search/split_array_largest_sum/README.md
BrianLusina 68db8ae
Update algorithms/search/binary_search/split_array_largest_sum/README.md
BrianLusina c1903b0
Update algorithms/search/binary_search/split_array_largest_sum/README.md
BrianLusina File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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] |
28 changes: 28 additions & 0 deletions
28
algorithms/dynamic_programming/decodeways/test_num_decodings.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
106 changes: 106 additions & 0 deletions
106
algorithms/search/binary_search/split_array_largest_sum/README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
|
|
||
|  | ||
|  | ||
|  | ||
|  | ||
|
|
||
| ## 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: | ||
|
|
||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|
|
||
| ### 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. |
87 changes: 87 additions & 0 deletions
87
algorithms/search/binary_search/split_array_largest_sum/__init__.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
Binary file added
BIN
+91 KB
...h/split_array_largest_sum/images/examples/split_array_largest_sum_example_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+80.3 KB
...h/split_array_largest_sum/images/examples/split_array_largest_sum_example_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+74.1 KB
...h/split_array_largest_sum/images/examples/split_array_largest_sum_example_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+98.7 KB
...h/split_array_largest_sum/images/examples/split_array_largest_sum_example_4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+55.8 KB
...split_array_largest_sum/images/solutions/split_array_largest_sum_solution_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+68.8 KB
...plit_array_largest_sum/images/solutions/split_array_largest_sum_solution_10.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+65.2 KB
...plit_array_largest_sum/images/solutions/split_array_largest_sum_solution_11.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+99 KB
...plit_array_largest_sum/images/solutions/split_array_largest_sum_solution_12.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+61 KB
...plit_array_largest_sum/images/solutions/split_array_largest_sum_solution_13.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+88.1 KB
...plit_array_largest_sum/images/solutions/split_array_largest_sum_solution_14.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+84.9 KB
...plit_array_largest_sum/images/solutions/split_array_largest_sum_solution_15.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+64.3 KB
...plit_array_largest_sum/images/solutions/split_array_largest_sum_solution_16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+99.5 KB
...plit_array_largest_sum/images/solutions/split_array_largest_sum_solution_17.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+59.7 KB
...plit_array_largest_sum/images/solutions/split_array_largest_sum_solution_18.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+94.6 KB
...plit_array_largest_sum/images/solutions/split_array_largest_sum_solution_19.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+68.7 KB
...split_array_largest_sum/images/solutions/split_array_largest_sum_solution_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+85.1 KB
...plit_array_largest_sum/images/solutions/split_array_largest_sum_solution_20.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+84.9 KB
...split_array_largest_sum/images/solutions/split_array_largest_sum_solution_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+68.6 KB
...split_array_largest_sum/images/solutions/split_array_largest_sum_solution_4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+66.9 KB
...split_array_largest_sum/images/solutions/split_array_largest_sum_solution_5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+63.8 KB
...split_array_largest_sum/images/solutions/split_array_largest_sum_solution_6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+103 KB
...split_array_largest_sum/images/solutions/split_array_largest_sum_solution_7.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+84.9 KB
...split_array_largest_sum/images/solutions/split_array_largest_sum_solution_8.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+81.8 KB
...split_array_largest_sum/images/solutions/split_array_largest_sum_solution_9.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.