-
Notifications
You must be signed in to change notification settings - Fork 2
feat(algorithms, dynamic programming): dynamic programming problems #151
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
8 commits
Select commit
Hold shift + click to select a range
0cb2f0c
feat(algorithms, dynamic-programming): palindromic substrings
BrianLusina 780f9dc
updating DIRECTORY.md
fc749ac
feat(algorithms, heap): minimum machines to schedule tasks
BrianLusina 24025fa
updating DIRECTORY.md
6e149e5
Update algorithms/dynamic_programming/palindromic_substring/README.md
BrianLusina 97a8c16
Update algorithms/dynamic_programming/palindromic_substring/test_long…
BrianLusina 4d46a38
Update algorithms/heap/schedule_tasks/README.md
BrianLusina 65dc250
test: fix failing test
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
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
114 changes: 114 additions & 0 deletions
114
algorithms/dynamic_programming/palindromic_substring/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,114 @@ | ||
| # Palindromic Substring | ||
|
|
||
| ## Palindromic Substring | ||
|
|
||
| Given a string, s, return the number of palindromic substrings contained in it. A substring is a contiguous sequence of | ||
| characters in a string. A palindrome is a phrase, word, or sequence that reads the same forward and backward. | ||
|
|
||
| ### Constraints | ||
|
|
||
| - 1 <= `s.length` <= 1000 | ||
| - `s` consists of lower English characters | ||
|
|
||
| ### Examples | ||
|
|
||
|  | ||
|  | ||
|
|
||
| ### Solution | ||
|
|
||
| If we look at the example above, we notice that any substring of length 3 contains a substring of length 1 at the center. | ||
| Although we had already checked all substrings of length 1, our algorithm rechecked them for substrings of longer lengths. | ||
| This rechecking consumes a lot of time, which can be avoided by storing and reusing the results of the earlier computations. | ||
| To do this, we can create a lookup table, dp, of size n×n, where n is the length of the input string. Each cell dp[i][j] | ||
| will store whether the string s[i..j] is a palindromic substring. If the cell dp[i][j] holds the result of the earlier | ||
| computation, we will utilize it in O(1) lookup time instead of making a recursive call again. | ||
|
|
||
| 1. First, we initialize a count variable with 0, which will count the number of palindromic substrings in s. | ||
| 2. A lookup table is initialized with FALSE. | ||
| 3. Base case 1: The diagonal in the lookup table is populated with TRUE because any cell in the diagonal corresponds to | ||
| a substring of length one, and any string of length one is always a palindrome. The number of one-letter palindromic | ||
| strings (i.e., the number of elements in the diagonal) is also added to the count. | ||
| 4. Base case 2: We check whether all two-letter substrings are palindromes and update the count and dp accordingly. We | ||
| do this by iterating over the string, comparing s[i] and s[i+1], and storing the result at dp[i][i+1]. After that, we | ||
| also increment the count if the value of dp[i][i+1] is TRUE, which tells us that the two-letter substring was a | ||
| palindrome. | ||
| 5. After these base cases, we check all substrings of lengths greater than two. However, we only compare the first and | ||
| the last characters. The rest of the string is checked using the lookup table. For example, for a given string “zing”, | ||
| we want to check whether “zin” is a palindrome. We’ll only compare ‘z’ and ‘n’ and check the value of dp[1][1], which | ||
| will tell whether the remaining string “i”, represented by s[1..1], is a palindrome. We’ll take the logical AND of | ||
| these two results and store it at dp[0][2] because “zin” is represented by the substring s[0..2]. This way, we’ll | ||
| avoid redundant computations and check all possible substrings using the lookup table. | ||
|
|
||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|
|
||
| #### Solution Summary | ||
|
|
||
| To recap, the solution to this problem can be divided into the following five main parts: | ||
|
|
||
| 1. We count all one-letter substrings since any one-letter string is always a palindrome. These results are also stored | ||
| in a lookup table to be used later. | ||
| 2. Next, the algorithm checks all two-letter substrings and updates the count and the lookup table accordingly. | ||
| 3. After these base cases, the algorithm checks all possible substrings of lengths greater than two. However, it only | ||
| compares the first and last characters, and the rest of the substring is checked using the lookup table. | ||
| 4. Whenever a palindromic substring is found, the count and the lookup table are updated accordingly. | ||
| 5. After checking all possible substrings, the algorithm terminates and returns the count of the palindromic substrings. | ||
|
|
||
| #### Complexity Analysis | ||
|
|
||
| ##### Time Complexity | ||
|
|
||
| The time complexity of this algorithm is O(n^2), where n is the length of the input string. This is the time required to | ||
| populate the lookup table. | ||
|
|
||
| ##### Space Complexity | ||
|
|
||
| The space complexity of this algorithm is O(n^2), where n is the length of the input string. This is the space occupied | ||
| by the lookup table. | ||
|
|
||
| --- | ||
|
|
||
| ## Longest Palindromic Substring | ||
|
|
||
| Problem Description | ||
|
|
||
| Given a string A of size N, find and return the longest palindromic substring in A. | ||
|
|
||
| Substring of string A is A[i...j] where 0 <= i <= j < len(A) | ||
|
|
||
| Palindrome string: | ||
|
|
||
| A string which reads the same backwards. More formally, A is palindrome if reverse(A) = A. | ||
|
|
||
| Incase of conflict, return the substring which occurs first ( with the least starting index). | ||
|
|
||
| Input Format | ||
| First and only argument is a string A. | ||
|
|
||
| Output Format | ||
| Return a string denoting the longest palindromic substring of string A. | ||
|
|
||
| Example Input | ||
| A = "aaaabaaa" | ||
|
|
||
| Example Output | ||
| "aaabaaa" | ||
|
|
||
| Example Explanation | ||
| We can see that longest palindromic substring is of length 7 and the string is "aaabaaa". |
66 changes: 66 additions & 0 deletions
66
algorithms/dynamic_programming/palindromic_substring/__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,66 @@ | ||
| def count_palindromic_substrings(s: str) -> int: | ||
| """ | ||
| Counts the number of palindromic substrings that can be found in the given string | ||
| Args: | ||
| s(str): string to check for palindromic substrings | ||
| Returns: | ||
| int: number of palindromic substrings | ||
| """ | ||
| n = len(s) | ||
| dp = [[False] * n for _ in range(n)] | ||
|
|
||
| count = 0 | ||
| # Set all the strings of length 1 to true, these are all palindromes | ||
| for i in range(n): | ||
| count += 1 | ||
| dp[i][i] = True | ||
|
|
||
| # iterate over pairs i, i+1, checking if they are equal, if they are, then they are palindromes | ||
| for i in range(n - 1): | ||
| if s[i] == s[i + 1]: | ||
| count += 1 | ||
| dp[i][i + 1] = True | ||
|
|
||
| for diff in range(2, n): | ||
| for i in range(n - diff): | ||
| j = i + diff | ||
| if s[i] == s[j] and dp[i + 1][j - 1]: | ||
| count += 1 | ||
| dp[i][j] = True | ||
|
|
||
| return count | ||
|
|
||
|
|
||
| def count_palindromic_substrings_2(s: str) -> int: | ||
| """ | ||
| Counts the number of palindromic substrings that can be found in the given string | ||
| Args: | ||
| s(str): string to check for palindromic substrings | ||
| Returns: | ||
| int: number of palindromic substrings | ||
| """ | ||
| n = len(s) | ||
| dp = [[False] * n for _ in range(n)] | ||
|
|
||
| count = 0 | ||
| # Set all the strings of length 1 to true, these are all palindromes | ||
| for i in range(n): | ||
| count += 1 | ||
| dp[i][i] = True | ||
|
|
||
| # iterate over pairs i, i+1, checking if they are equal, if they are, then they are palindromes | ||
| for i in range(n - 1): | ||
| dp[i][i + 1] = s[i] == s[i + 1] | ||
| # A boolean value is added to the count where True means 1 and False means 0 | ||
| count += dp[i][i + 1] | ||
|
|
||
| # Substrings of lengths greater than 2 | ||
| for length in range(3, n + 1): | ||
| i = 0 | ||
| # Checking every possible substring of any specific length | ||
| for j in range(length - 1, n): | ||
| dp[i][j] = dp[i + 1][j - 1] and (s[i] == s[j]) | ||
| count += dp[i][j] | ||
| i += 1 | ||
|
|
||
| return count |
Binary file added
BIN
+65.8 KB
...mming/palindromic_substring/images/examples/palindromic_substring_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
+47 KB
...mming/palindromic_substring/images/examples/palindromic_substring_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
+114 KB
...ing/palindromic_substring/images/solutions/palindromic_substring_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
+86.4 KB
...ng/palindromic_substring/images/solutions/palindromic_substring_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
+98.1 KB
...ng/palindromic_substring/images/solutions/palindromic_substring_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
+113 KB
...ng/palindromic_substring/images/solutions/palindromic_substring_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
+112 KB
...ng/palindromic_substring/images/solutions/palindromic_substring_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
+89.4 KB
...ng/palindromic_substring/images/solutions/palindromic_substring_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
+106 KB
...ng/palindromic_substring/images/solutions/palindromic_substring_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
+97 KB
...ng/palindromic_substring/images/solutions/palindromic_substring_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
+166 KB
...ng/palindromic_substring/images/solutions/palindromic_substring_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
+108 KB
...ing/palindromic_substring/images/solutions/palindromic_substring_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
+159 KB
...ing/palindromic_substring/images/solutions/palindromic_substring_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
+83.5 KB
...ing/palindromic_substring/images/solutions/palindromic_substring_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
+114 KB
...ing/palindromic_substring/images/solutions/palindromic_substring_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
+83.9 KB
...ing/palindromic_substring/images/solutions/palindromic_substring_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
+98.6 KB
...ing/palindromic_substring/images/solutions/palindromic_substring_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
+104 KB
...ing/palindromic_substring/images/solutions/palindromic_substring_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
+84.5 KB
...ing/palindromic_substring/images/solutions/palindromic_substring_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.
5 changes: 3 additions & 2 deletions
5
...lindrome/longest_palindromic_substring.py → ...ubstring/longest_palindromic_substring.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
30 changes: 30 additions & 0 deletions
30
algorithms/dynamic_programming/palindromic_substring/test_longest_palindromic_substring.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,30 @@ | ||
| import unittest | ||
| from parameterized import parameterized | ||
| from algorithms.dynamic_programming.palindromic_substring.longest_palindromic_substring import ( | ||
| longest_palindromic_substring, | ||
| ) | ||
|
|
||
| LONGEST_PALINDROMIC_SUBSTRING_TEST_CASES = [ | ||
| ("", ""), | ||
| ("a", "a"), | ||
| ("aab", "aa"), | ||
| ("baa", "aa"), | ||
| ("mnm", "mnm"), | ||
| ("zzz", "zzz"), | ||
| ("cat", "c"), | ||
| ("lever", "eve"), | ||
| ("xyxxyz", "yxxy"), | ||
| ("wwwwwwwwww", "wwwwwwwwww"), | ||
| ("tattarrattat", "tattarrattat"), | ||
| ] | ||
|
|
||
|
|
||
| class LongestPalindromicSubstringTestCase(unittest.TestCase): | ||
| @parameterized.expand(LONGEST_PALINDROMIC_SUBSTRING_TEST_CASES) | ||
| def test_longest_palindromic_substrings(self, s: str, expected: str): | ||
| actual = longest_palindromic_substring(s) | ||
| self.assertEqual(expected, actual) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| unittest.main() | ||
34 changes: 34 additions & 0 deletions
34
algorithms/dynamic_programming/palindromic_substring/test_palindromic_substring.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,34 @@ | ||
| import unittest | ||
| from parameterized import parameterized | ||
| from algorithms.dynamic_programming.palindromic_substring import ( | ||
| count_palindromic_substrings, | ||
| count_palindromic_substrings_2, | ||
| ) | ||
|
|
||
| COUNT_PALINDROMIC_SUBSTRINGS_TEST_CASES = [ | ||
| ("abc", 3), | ||
| ("aaa", 6), | ||
| ("mnm", 4), | ||
| ("zzz", 6), | ||
| ("cat", 3), | ||
| ("lever", 6), | ||
| ("xyxxyz", 9), | ||
| ("wwwwwwwwww", 55), | ||
| ("tattarrattat", 24), | ||
| ] | ||
|
|
||
|
|
||
| class CountPalindromicSubstringsTestCase(unittest.TestCase): | ||
| @parameterized.expand(COUNT_PALINDROMIC_SUBSTRINGS_TEST_CASES) | ||
| def test_count_palindromic_substrings(self, s: str, expected: int): | ||
| actual = count_palindromic_substrings(s) | ||
| self.assertEqual(expected, actual) | ||
|
|
||
| @parameterized.expand(COUNT_PALINDROMIC_SUBSTRINGS_TEST_CASES) | ||
| def test_count_palindromic_substrings_2(self, s: str, expected: int): | ||
| actual = count_palindromic_substrings_2(s) | ||
| self.assertEqual(expected, actual) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| unittest.main() |
File renamed without changes.
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
File renamed without changes.
Empty file.
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,78 @@ | ||
| # Schedule Tasks on Minimum Machines | ||
|
|
||
| We are given an input array, tasks, where tasks[i]=[starti ,endi] represents the start and end times of n tasks. Our | ||
| goal is to schedule these tasks on machines given the following criteria: | ||
|
|
||
| - A machine can execute only one task at a time. | ||
| - A machine can begin executing a new task immediately after completing the previous one. | ||
| - An unlimited number of machines are available. | ||
|
|
||
| Find the minimum number of machines required to complete these n tasks. | ||
|
|
||
| ## Constraints | ||
|
|
||
| - n == `tasks.length` | ||
| - 1 <= `tasks.length` <= 10^3 | ||
| - 0 <= `tasks[i].start` < `tasks[i].end` <= 10^4 | ||
|
|
||
| ## Examples | ||
|
|
||
|  | ||
|  | ||
|  | ||
|  | ||
|
|
||
| ## Solution | ||
|
|
||
| The core intuition for solving this problem is to allocate tasks to the minimum number of machines by reusing machines | ||
| whenever possible. The algorithm efficiently manages machine availability by sorting tasks by their start times and using | ||
| a min heap to track end times. If the earliest available machine (top of the heap) finishes before or as a task starts, | ||
| it is reused and removed from the heap. Otherwise, a new machine is allocated, and the current task’s end time is pushed | ||
| into the heap. The heap size at the end represents the minimum number of machines required. | ||
|
|
||
| Using the intuition above, we implement the algorithm as follows: | ||
|
|
||
| 1. Sort the tasks array by the start time of each task to process them in chronological order. | ||
| 2. Initialize a min heap (machines) to keep track of the end times of tasks currently using machines. | ||
| 3. Iterate over each task in the sorted tasks array. | ||
| - Extract the start and end times of the current task. | ||
| - Check if the machine with the earliest finish time is free, i.e., top of machines is less than or equal to the | ||
| current task’s start time. If it is, remove it from the heap, as the machine can be reused. | ||
| - Push the end time of the current task into the heap, indicating that a machine is now in use until that time. | ||
| 4. After processing all tasks, return the size of the heap, which represents the minimum number of machines required. | ||
|
|
||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|
|
||
| ### Time Complexity | ||
|
|
||
| The time complexity of the above algorithm is O(nlogn), where n is the number of tasks represented by the length of the | ||
| tasks array. This is because: | ||
|
|
||
| - Sorting the array takes O(nlogn). | ||
| - The total cost for heap operations is O(nlogn) because we process n tasks, and each operation on the min-heap has a | ||
| time complexity of O(logn). | ||
|
|
||
| Therefore, the overall time complexity is O(nlogn). | ||
|
|
||
| ### Space Complexity | ||
|
|
||
| The algorithm’s space complexity is O(n) because the min heap can grow up to a maximum size of n if every task requires | ||
| a separate machine. |
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.