From 94dad4809f212e2773ce6540e0da5094fcc60f0a Mon Sep 17 00:00:00 2001 From: Sean Date: Fri, 11 Oct 2019 13:37:22 +0800 Subject: [PATCH 01/12] add_integer_divide --- README.md | 1 + algorithms/dp/__init__.py | 1 + algorithms/dp/int_divide.py | 48 +++++++++++++++++++++++++++++++++++++ tests/test_dp.py | 22 +++++++++++------ 4 files changed, 65 insertions(+), 7 deletions(-) create mode 100644 algorithms/dp/int_divide.py diff --git a/README.md b/README.md index f30d4520e..39d906865 100644 --- a/README.md +++ b/README.md @@ -129,6 +129,7 @@ If you want to uninstall algorithms, it is as simple as: - [combination_sum](algorithms/dp/combination_sum.py) - [egg_drop](algorithms/dp/egg_drop.py) - [house_robber](algorithms/dp/house_robber.py) + - [int_divide](algorithms/dp/int_divide.py) - [job_scheduling](algorithms/dp/job_scheduling.py) - [knapsack](algorithms/dp/knapsack.py) - [longest_increasing](algorithms/dp/longest_increasing.py) diff --git a/algorithms/dp/__init__.py b/algorithms/dp/__init__.py index 892540972..f37f3c677 100644 --- a/algorithms/dp/__init__.py +++ b/algorithms/dp/__init__.py @@ -18,3 +18,4 @@ from .regex_matching import * from .rod_cut import * from .word_break import * +from .int_divide import * \ No newline at end of file diff --git a/algorithms/dp/int_divide.py b/algorithms/dp/int_divide.py new file mode 100644 index 000000000..be86365e8 --- /dev/null +++ b/algorithms/dp/int_divide.py @@ -0,0 +1,48 @@ +""" +Given positive integer n, find an algorithm to find the number of non-negative number division, or descomposition. + +Example 1: +Input: 4 +Output: 5 +Explaination: +4=4 +4=3+1 +4=2+2 +4=2+1+1 +4=1+1+1+1 + +Example : +Input: 7 +Output: 15 +Explaination: +7=7 +7=6+1 +7=5+2 +7=5+1+1 +7=4+3 +7=4+2+1 +7=4+1+1+1 +7=3+3+1 +7=3+2+2 +7=3+2+1+1 +7=3+1+1+1+1 +7=2+2+2+1 +7=2+2+1+1+1 +7=2+1+1+1+1+1 +7=1+1+1+1+1+1+1 + +""" + + +def divide(n): + arr = [[0 for i in range(n + 1)] for j in range(n + 1)] + arr[1][1] = 1 + for i in range(1, n + 1): + for j in range(1, n + 1): + if i < j: + arr[i][j] = arr[i][i] + elif i == j: + arr[i][j] = 1 + arr[i][j - 1] + else: + arr[i][j] = arr[i][j - 1] + arr[i - j][j] + return arr[n][n] diff --git a/tests/test_dp.py b/tests/test_dp.py index 08f6bd0a9..cd1dde291 100644 --- a/tests/test_dp.py +++ b/tests/test_dp.py @@ -10,7 +10,8 @@ house_robber, Job, schedule, Item, get_maximum_value, - longest_increasing_subsequence + longest_increasing_subsequence, + int_divide ) @@ -31,7 +32,7 @@ class TestClimbingStairs(unittest.TestCase): def test_climb_stairs(self): self.assertEqual(climb_stairs(2), 2) self.assertEqual(climb_stairs(10), 89) - + def test_climb_stairs_optimized(self): self.assertEqual(climb_stairs_optimized(2), 2) self.assertEqual(climb_stairs_optimized(10), 89) @@ -46,7 +47,7 @@ def test_count(self): class TestCombinationSum(unittest.TestCase): def test_combination_sum_topdown(self): self.assertEqual(combination_sum_topdown([1, 2, 3], 4), 7) - + def test_combination_sum_bottom_up(self): self.assertEqual(combination_sum_bottom_up([1, 2, 3], 4), 7) @@ -68,11 +69,11 @@ class TestFib(unittest.TestCase): def test_fib_recursive(self): self.assertEqual(fib_recursive(10), 55) self.assertEqual(fib_recursive(30), 832040) - + def test_fib_list(self): self.assertEqual(fib_list(10), 55) self.assertEqual(fib_list(30), 832040) - + def test_fib_iter(self): self.assertEqual(fib_iter(10), 55) self.assertEqual(fib_iter(30), 832040) @@ -85,7 +86,7 @@ class TestHosoyaTriangle(unittest.TestCase): Arguments: unittest {[type]} -- [description] """ - + def test_hosoya(self): self.assertEqual([1], hosoya_testing(1)) self.assertEqual([1, @@ -108,7 +109,7 @@ def test_hosoya(self): hosoya_testing(10)) -class TestHouseRobber(unittest.TestCase): +class TestHouseRobber(unittest.TestCase): def test_house_robber(self): self.assertEqual(44, house_robber([1, 2, 16, 3, 15, 3, 12, 1])) @@ -134,5 +135,12 @@ def test_longest_increasing_subsequence(self): self.assertEqual(5, longest_increasing_subsequence(sequence)) +class TestIntDivide(unittest.TestCase): + def test_int_divide(self): + self.assertEqual(5, int_divide(4)) + self.assertEqual(42, int_divide(10)) + self.assertEqual(204226, int_divide(50)) + + if __name__ == '__main__': unittest.main() From e6b77de4ebb2089cf70296c1dec81bb4bbce9034 Mon Sep 17 00:00:00 2001 From: Sean Date: Fri, 11 Oct 2019 13:38:37 +0800 Subject: [PATCH 02/12] add_integer_divide --- algorithms/dp/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/algorithms/dp/__init__.py b/algorithms/dp/__init__.py index f37f3c677..c96a9b334 100644 --- a/algorithms/dp/__init__.py +++ b/algorithms/dp/__init__.py @@ -18,4 +18,4 @@ from .regex_matching import * from .rod_cut import * from .word_break import * -from .int_divide import * \ No newline at end of file +from .int_divide import * From 90fbaabea8747c52980b78eb2ae88b9998167aed Mon Sep 17 00:00:00 2001 From: Sean Date: Fri, 11 Oct 2019 13:44:04 +0800 Subject: [PATCH 03/12] add_integer_divide --- algorithms/dp/int_divide.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/algorithms/dp/int_divide.py b/algorithms/dp/int_divide.py index be86365e8..68e147959 100644 --- a/algorithms/dp/int_divide.py +++ b/algorithms/dp/int_divide.py @@ -1,6 +1,8 @@ """ Given positive integer n, find an algorithm to find the number of non-negative number division, or descomposition. +The complexity is O(n^2). + Example 1: Input: 4 Output: 5 From 823a7437e2175a2a8d0814f18ebc861f6dacdf03 Mon Sep 17 00:00:00 2001 From: Sean Date: Fri, 11 Oct 2019 14:00:32 +0800 Subject: [PATCH 04/12] add_integer_divide --- algorithms/dp/int_divide.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/algorithms/dp/int_divide.py b/algorithms/dp/int_divide.py index 68e147959..86ba8cbb6 100644 --- a/algorithms/dp/int_divide.py +++ b/algorithms/dp/int_divide.py @@ -36,7 +36,7 @@ """ -def divide(n): +def int_divide(n): arr = [[0 for i in range(n + 1)] for j in range(n + 1)] arr[1][1] = 1 for i in range(1, n + 1): From 2b1df715d4c0ef6717189cac6915c86b328733bb Mon Sep 17 00:00:00 2001 From: Sean Date: Sun, 20 Oct 2019 09:16:15 +0800 Subject: [PATCH 05/12] README updated --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 39d906865..a99ff7a6b 100644 --- a/README.md +++ b/README.md @@ -371,8 +371,7 @@ If you want to uninstall algorithms, it is as simple as: - [simplify_path](algorithms/unix/path/simplify_path.py) - [union-find](algorithms/union-find) - [count_islands](algorithms/union-find/count_islands.py) -- [machine-learning](algorithms/machine-learning) - - [nearest neighbor classification](algorithms/machine-learning/nearest_neighbor.py) + ## Contributors From 90d0c729d19a796e3c59a3e2b31e63f4c6fb86b2 Mon Sep 17 00:00:00 2001 From: Sean Date: Wed, 23 Oct 2019 23:17:53 +0800 Subject: [PATCH 06/12] Manacher's algorithm --- README.md | 3 +- algorithms/strings/__init__.py | 1 + .../strings/longest_palindromic_substring.py | 44 +++++++++++++++++++ tests/test_strings.py | 22 ++++++++-- 4 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 algorithms/strings/longest_palindromic_substring.py diff --git a/README.md b/README.md index a127f59b0..dea78f2c9 100644 --- a/README.md +++ b/README.md @@ -318,8 +318,9 @@ If you want to uninstall algorithms, it is as simple as: - [longest_common_prefix](algorithms/strings/longest_common_prefix.py) - [rotate](algorithms/strings/rotate.py) - [first_unique_char](algorithms/strings/first_unique_char.py) - - [repeat_substring](algorithms/strings/repeat_substring.py) + - [repeat_substring](algorithms/strings/repeat_substring.py) - [atbash_cipher](algorithms/strings/atbash_cipher.py) + - [longest_palindromic_substring](algorithms/strings/longest_palindromic_substring.py) - [tree](algorithms/tree) - [bst](algorithms/tree/bst) - [array_to_bst](algorithms/tree/bst/array_to_bst.py) diff --git a/algorithms/strings/__init__.py b/algorithms/strings/__init__.py index 9110a0f2c..56e01b415 100644 --- a/algorithms/strings/__init__.py +++ b/algorithms/strings/__init__.py @@ -35,3 +35,4 @@ from .first_unique_char import * from .repeat_substring import * from .atbash_cipher import * +from longest_palindromic_substring import * diff --git a/algorithms/strings/longest_palindromic_substring.py b/algorithms/strings/longest_palindromic_substring.py new file mode 100644 index 000000000..3b36089b7 --- /dev/null +++ b/algorithms/strings/longest_palindromic_substring.py @@ -0,0 +1,44 @@ +''' +Given string s, find the longest palindromic substring. + +Example1: + +* input: "babad" +* output: "bab" or "aba" + +Example2: + +* input: "cbbd" +* output: "bb" + +Manacher's algorithm + +''' + +def longestPalindrome(s): + if len(s) < 2: + return s + + n_str = '#' + '#'.join(s) + '#' + p = [0] * len(n_str) + mx, loc = 0, 0 + index, maxlen = 0, 0 + for i in range(len(n_str)): + if i < mx and 2 * loc - i < len(n_str): + p[i] = min(mx - i, p[2 * loc - i]) + else: + p[i] = 1 + + while p[i] + i < len(n_str) and i - p[i] >= 0 and n_str[ + i - p[i]] == n_str[i + p[i]]: + p[i] += 1 + + if i + p[i] > mx: + mx = i + p[i] + loc = i + + if p[i] > maxlen: + index = i + maxlen = p[i] + s = n_str[index - p[index] + 1:index + p[index]] + return s.replace('#', '') \ No newline at end of file diff --git a/tests/test_strings.py b/tests/test_strings.py index 02abc6f05..e022843fb 100644 --- a/tests/test_strings.py +++ b/tests/test_strings.py @@ -37,7 +37,8 @@ rotate, first_unique_char, repeat_substring, - atbash + atbash, + longestPalindrome ) import unittest @@ -525,12 +526,27 @@ class TestAtbashCipher(unittest.TestCase): Arguments: unittest {[type]} -- [description] """ - + def test_atbash_cipher(self): self.assertEqual("zyxwvutsrqponml", atbash("abcdefghijklmno")) self.assertEqual("KbgslM", atbash("PythoN")) self.assertEqual("AttaCK at DawN", atbash("ZggzXP zg WzdM")) self.assertEqual("ZggzXP zg WzdM", atbash("AttaCK at DawN")) - + + +class TestLongestPalindromicSubstring(unittest.TestCase): + """[summary] + Test for the file longest_palindromic_substring.py + + Arguments: + unittest {[type]} -- [description] + """ + def test_longest_palindromic_substring(self): + self.assertEqual("cbbd", longestPalindrome("bb")) + self.assertEqual("abba", longestPalindrome("abba")) + self.assertEqual("aaaa", longestPalindrome("aaaa")) + self.assertEqual("cabba", longestPalindrome("abba")) + + if __name__ == "__main__": unittest.main() From 5d2a21f43aaf5c46f84b5e05b9ffa749bc7737af Mon Sep 17 00:00:00 2001 From: Sean Date: Thu, 24 Oct 2019 07:43:14 +0800 Subject: [PATCH 07/12] Manacher's algorithm --- algorithms/strings/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/algorithms/strings/__init__.py b/algorithms/strings/__init__.py index 56e01b415..2d12a31ee 100644 --- a/algorithms/strings/__init__.py +++ b/algorithms/strings/__init__.py @@ -35,4 +35,4 @@ from .first_unique_char import * from .repeat_substring import * from .atbash_cipher import * -from longest_palindromic_substring import * +from .longest_palindromic_substring import * From 97c6ab1bd37dd272b311aa35960e24a749891b90 Mon Sep 17 00:00:00 2001 From: Sean Date: Thu, 24 Oct 2019 07:46:37 +0800 Subject: [PATCH 08/12] add Manacher's algorithm --- tests/test_strings.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_strings.py b/tests/test_strings.py index e022843fb..3baa9e9ff 100644 --- a/tests/test_strings.py +++ b/tests/test_strings.py @@ -542,10 +542,10 @@ class TestLongestPalindromicSubstring(unittest.TestCase): unittest {[type]} -- [description] """ def test_longest_palindromic_substring(self): - self.assertEqual("cbbd", longestPalindrome("bb")) + self.assertEqual("bb", longestPalindrome("cbbd")) self.assertEqual("abba", longestPalindrome("abba")) self.assertEqual("aaaa", longestPalindrome("aaaa")) - self.assertEqual("cabba", longestPalindrome("abba")) + self.assertEqual("abba", longestPalindrome("cabba")) if __name__ == "__main__": From 719d08d801a828f9d10e296273f8a03c81136fea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E4=BF=8A=E4=B9=89?= <32086937+Sean16SYSU@users.noreply.github.com> Date: Sun, 21 Jun 2020 09:33:42 +0800 Subject: [PATCH 09/12] with more snack test case --- algorithms/strings/longest_palindromic_substring.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/algorithms/strings/longest_palindromic_substring.py b/algorithms/strings/longest_palindromic_substring.py index 3b36089b7..74f4fcdaf 100644 --- a/algorithms/strings/longest_palindromic_substring.py +++ b/algorithms/strings/longest_palindromic_substring.py @@ -3,13 +3,13 @@ Example1: -* input: "babad" -* output: "bab" or "aba" +* input: "dasdasdasdasdasdadsa" +* output: "asdadsa" Example2: -* input: "cbbd" -* output: "bb" +* input: "acdbbdaa" +* output: "dbbd" Manacher's algorithm @@ -41,4 +41,4 @@ def longestPalindrome(s): index = i maxlen = p[i] s = n_str[index - p[index] + 1:index + p[index]] - return s.replace('#', '') \ No newline at end of file + return s.replace('#', '') From 5262259e301a378056d07a228a821808abd6ba5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E4=BF=8A=E4=B9=89?= <32086937+Sean16SYSU@users.noreply.github.com> Date: Sun, 21 Jun 2020 09:36:23 +0800 Subject: [PATCH 10/12] more snack cases for testing files --- tests/test_strings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_strings.py b/tests/test_strings.py index f5fa9b6ff..69fb9f924 100644 --- a/tests/test_strings.py +++ b/tests/test_strings.py @@ -548,7 +548,7 @@ class TestLongestPalindromicSubstring(unittest.TestCase): def test_longest_palindromic_substring(self): self.assertEqual("bb", longestPalindrome("cbbd")) self.assertEqual("abba", longestPalindrome("abba")) - self.assertEqual("aaaa", longestPalindrome("aaaa")) + self.assertEqual("asdadsa", longestPalindrome("dasdasdasdasdasdadsa")) self.assertEqual("abba", longestPalindrome("cabba")) From e1c5ce746ebe556418cd6fbeb70584149d3770fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E4=BF=8A=E4=B9=89?= <32086937+Sean16SYSU@users.noreply.github.com> Date: Sun, 21 Jun 2020 12:50:27 +0800 Subject: [PATCH 11/12] change the name of function `longestPalindrome` to `longest_palindrome` --- algorithms/strings/longest_palindromic_substring.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/algorithms/strings/longest_palindromic_substring.py b/algorithms/strings/longest_palindromic_substring.py index 74f4fcdaf..ad0c831b9 100644 --- a/algorithms/strings/longest_palindromic_substring.py +++ b/algorithms/strings/longest_palindromic_substring.py @@ -15,7 +15,7 @@ ''' -def longestPalindrome(s): +def longest_palindrome(s): if len(s) < 2: return s From 6da6787fe9b35f4017c667eefdc108b7dfbe1231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E4=BF=8A=E4=B9=89?= <32086937+Sean16SYSU@users.noreply.github.com> Date: Sun, 21 Jun 2020 12:52:37 +0800 Subject: [PATCH 12/12] test changed because the name of function changed --- tests/test_strings.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test_strings.py b/tests/test_strings.py index 69fb9f924..b8750b1f8 100644 --- a/tests/test_strings.py +++ b/tests/test_strings.py @@ -38,7 +38,7 @@ first_unique_char, repeat_substring, atbash, - longestPalindrome, + longest_palindrome, knuth_morris_pratt ) @@ -546,10 +546,10 @@ class TestLongestPalindromicSubstring(unittest.TestCase): """ def test_longest_palindromic_substring(self): - self.assertEqual("bb", longestPalindrome("cbbd")) - self.assertEqual("abba", longestPalindrome("abba")) - self.assertEqual("asdadsa", longestPalindrome("dasdasdasdasdasdadsa")) - self.assertEqual("abba", longestPalindrome("cabba")) + self.assertEqual("bb", longest_palindrome("cbbd")) + self.assertEqual("abba", longest_palindrome("abba")) + self.assertEqual("asdadsa", longest_palindrome("dasdasdasdasdasdadsa")) + self.assertEqual("abba", longest_palindrome("cabba")) class TestKnuthMorrisPratt(unittest.TestCase):