Skip to content

Commit 48072b4

Browse files
author
Hai Hoang Dang
authored
PR to add some problem (keon#378)
* Add longest_common_prefix to string * Add brute force way for is_rotated, add rotate to string * Add first_unique_char to string * Add repeat_substring to string
1 parent 010dce3 commit 48072b4

File tree

8 files changed

+205
-3
lines changed

8 files changed

+205
-3
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,10 @@ If you want to uninstall algorithms, it is as simple as:
295295
- [count_binary_substring](algorithms/strings/count_binary_substring.py)
296296
- [repeat_string](algorithms/strings/repeat_string.py)
297297
- [min_distance](algorithms/strings/min_distance.py)
298+
- [longest_common_prefix](algorithms/strings/longest_common_prefix.py)
299+
- [rotate](algorithms/strings/rotate.py)
300+
- [first_unique_char](algorithms/strings/first_unique_char.py)
301+
- [repeat_substring](algorithms/strings/repeat_substring.py)
298302
- [tree](algorithms/tree)
299303
- [bst](algorithms/tree/tree/bst)
300304
- [array2bst](algorithms/tree/bst/array2bst.py)

algorithms/strings/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,7 @@
3030
from .repeat_string import *
3131
from .text_justification import *
3232
from .min_distance import *
33+
from .longest_common_prefix import *
34+
from .rotate import *
35+
from .first_unique_char import *
36+
from .repeat_substring import *
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"""
2+
Given a string, find the first non-repeating character in it and return it's
3+
index. If it doesn't exist, return -1.
4+
5+
For example:
6+
s = "leetcode"
7+
return 0.
8+
9+
s = "loveleetcode",
10+
return 2.
11+
12+
Reference: https://leetcode.com/problems/first-unique-character-in-a-string/description/
13+
"""
14+
def first_unique_char(s):
15+
"""
16+
:type s: str
17+
:rtype: int
18+
"""
19+
if (len(s) == 1):
20+
return 0
21+
ban = []
22+
for i in range(len(s)):
23+
if all(s[i] != s[k] for k in range(i + 1, len(s))) == True and s[i] not in ban:
24+
return i
25+
else:
26+
ban.append(s[i])
27+
return -1

algorithms/strings/is_rotated.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,26 @@
66
77
accepts two strings
88
returns bool
9+
Reference: https://leetcode.com/problems/rotate-string/description/
910
"""
1011

1112
def is_rotated(s1, s2):
1213
if len(s1) == len(s2):
1314
return s2 in s1 + s1
1415
else:
15-
return False
16+
return False
17+
18+
"""
19+
Another solution: brutal force
20+
Complexity: O(N^2)
21+
"""
22+
def is_rotated_v1(s1, s2):
23+
if len(s1) != len(s2):
24+
return False
25+
if len(s1) == 0:
26+
return True
27+
28+
for c in range(len(s1)):
29+
if all(s1[(c + i) % len(s1)] == s2[i] for i in range(len(s1))):
30+
return True
31+
return False
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
"""
2+
Write a function to find the longest common prefix string amongst an array of strings.
3+
4+
If there is no common prefix, return an empty string "".
5+
6+
Example 1:
7+
Input: ["flower","flow","flight"]
8+
Output: "fl"
9+
10+
Example 2:
11+
Input: ["dog","racecar","car"]
12+
Output: ""
13+
Explanation: There is no common prefix among the input strings.
14+
15+
Reference: https://leetcode.com/problems/longest-common-prefix/description/
16+
"""
17+
18+
"""
19+
First solution: Horizontal scanning
20+
"""
21+
def common_prefix(s1, s2):
22+
"Return prefix common of 2 strings"
23+
if not s1 or not s2:
24+
return ""
25+
k = 0
26+
while s1[k] == s2[k]:
27+
k = k + 1
28+
if k >= len(s1) or k >= len(s2):
29+
return s1[0:k]
30+
return s1[0:k]
31+
32+
def longest_common_prefix_v1(strs):
33+
if not strs:
34+
return ""
35+
result = strs[0]
36+
for i in range(len(strs)):
37+
result = common_prefix(result, strs[i])
38+
return result
39+
40+
"""
41+
Second solution: Vertical scanning
42+
"""
43+
def longest_common_prefix_v2(strs):
44+
if not strs:
45+
return ""
46+
for i in range(len(strs[0])):
47+
for string in strs[1:]:
48+
if i == len(string) or string[i] != strs[0][i]:
49+
return strs[0][0:i]
50+
return strs[0]
51+
52+
"""
53+
Third solution: Divide and Conquer
54+
"""
55+
def longest_common_prefix_v3(strs):
56+
if not strs:
57+
return ""
58+
return longest_common(strs, 0, len(strs) -1)
59+
60+
def longest_common(strs, left, right):
61+
if left == right:
62+
return strs[left]
63+
mid = (left + right) // 2
64+
lcp_left = longest_common(strs, left, mid)
65+
lcp_right = longest_common(strs, mid + 1, right)
66+
return common_prefix(lcp_left, lcp_right)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
"""
2+
Given a non-empty string check if it can be constructed by taking
3+
a substring of it and appending multiple copies of the substring together.
4+
5+
For example:
6+
Input: "abab"
7+
Output: True
8+
Explanation: It's the substring "ab" twice.
9+
10+
Input: "aba"
11+
Output: False
12+
13+
Input: "abcabcabcabc"
14+
Output: True
15+
Explanation: It's the substring "abc" four times.
16+
17+
Reference: https://leetcode.com/problems/repeated-substring-pattern/description/
18+
"""
19+
def repeat_substring(s):
20+
"""
21+
:type s: str
22+
:rtype: bool
23+
"""
24+
str = (s + s)[1:-1]
25+
return s in str

algorithms/strings/rotate.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
"""
2+
Given a strings s and int k, return a string that rotates k times
3+
4+
For example,
5+
rotate("hello", 2) return "llohe"
6+
rotate("hello", 5) return "hello"
7+
rotate("hello", 6) return "elloh"
8+
rotate("hello", 7) return "llohe"
9+
10+
accepts two strings
11+
returns bool
12+
"""
13+
def rotate(s, k):
14+
double_s = s + s
15+
if k <= len(s):
16+
return double_s[k:k + len(s)]
17+
else:
18+
return double_s[k-len(s):k]

tests/test_strings.py

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
int_to_roman,
1010
is_palindrome, is_palindrome_reverse,
1111
is_palindrome_two_pointer, is_palindrome_stack,
12-
is_rotated,
12+
is_rotated, is_rotated_v1,
1313
license_number,
1414
make_sentence,
1515
is_merge_recursive, is_merge_iterative,
@@ -32,7 +32,11 @@
3232
count_binary_substring,
3333
repeat_string,
3434
text_justification,
35-
min_distance
35+
min_distance,
36+
longest_common_prefix_v1, longest_common_prefix_v2, longest_common_prefix_v3,
37+
rotate,
38+
first_unique_char,
39+
repeat_substring
3640
)
3741

3842
import unittest
@@ -201,6 +205,21 @@ def test_is_rotated(self):
201205
self.assertFalse(is_rotated("hello", "lloh"))
202206
self.assertTrue(is_rotated("", ""))
203207

208+
def test_is_rotated_v1(self):
209+
self.assertTrue(is_rotated_v1("hello", "hello"))
210+
self.assertTrue(is_rotated_v1("hello", "llohe"))
211+
self.assertFalse(is_rotated_v1("hello", "helol"))
212+
self.assertFalse(is_rotated_v1("hello", "lloh"))
213+
self.assertTrue(is_rotated_v1("", ""))
214+
215+
216+
class TestRotated(unittest.TestCase):
217+
def test_rotate(self):
218+
self.assertEqual("llohe", rotate("hello", 2))
219+
self.assertEqual("hello", rotate("hello", 5))
220+
self.assertEqual("elloh", rotate("hello", 6))
221+
self.assertEqual("llohe", rotate("hello", 7))
222+
204223

205224
class TestLicenseNumber(unittest.TestCase):
206225
"""[summary]
@@ -475,6 +494,29 @@ def test_min_distance(self):
475494
self.assertEqual(2, min_distance("sea", "eat"))
476495
self.assertEqual(6, min_distance("abAlgocrithmf", "Algorithmmd"))
477496

497+
class TestLongestCommonPrefix(unittest.TestCase):
498+
def test_longest_common_prefix(self):
499+
# Test first solution
500+
self.assertEqual("fl", longest_common_prefix_v1(["flower","flow","flight"]))
501+
self.assertEqual("", longest_common_prefix_v1(["dog","racecar","car"]))
502+
# Test second solution
503+
self.assertEqual("fl", longest_common_prefix_v2(["flower","flow","flight"]))
504+
self.assertEqual("", longest_common_prefix_v2(["dog","racecar","car"]))
505+
# Test third solution
506+
self.assertEqual("fl", longest_common_prefix_v3(["flower","flow","flight"]))
507+
self.assertEqual("", longest_common_prefix_v3(["dog","racecar","car"]))
508+
509+
class TestFirstUniqueChar(unittest.TestCase):
510+
def test_first_unique_char(self):
511+
self.assertEqual(0, first_unique_char("leetcode"))
512+
self.assertEqual(2, first_unique_char("loveleetcode"))
513+
514+
class TestRepeatSubstring(unittest.TestCase):
515+
def test_repeat_substring(self):
516+
self.assertTrue(repeat_substring("abab"))
517+
self.assertFalse(repeat_substring("aba"))
518+
self.assertTrue(repeat_substring("abcabcabcabc"))
519+
478520

479521
if __name__ == "__main__":
480522
unittest.main()

0 commit comments

Comments
 (0)