Skip to content

Commit 0bf441d

Browse files
Meto TrajkovskiMeto Trajkovski
authored andcommitted
Added more string solutions
1 parent d0a71a1 commit 0bf441d

9 files changed

+415
-9
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,12 @@ def name_of_problem_2(params):
6868
###########
6969
# Testing #
7070
###########
71-
# result = 'result'
71+
# Test 1
72+
# correct result => 'result'
7273
print(name_of_problem('example'))
7374

74-
# result = 'result2'
75+
# Test 2
76+
# correct result => 'result2'
7577
print(name_of_problem_2('example2'))
7678
```
7779

Strings/anagram_indicies.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
'''
2+
Anagram indicies
3+
4+
Given a word and a string S, find all starting indices in S which are anagrams of word.
5+
(An anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once)
6+
7+
Input: s='abxaba' word='ab'
8+
Output: [0, 3, 4]
9+
Output explanation: For example, given that word is 'ab', and S is 'abxaba', return 0 'ab', 3 'ab', and 4'ba'.
10+
11+
=========================================
12+
Create a structure for counting the ferquency of letters (the structure is a simple dictionary).
13+
Similar to sliding window solution, add letters into the structure from the front of sliding window
14+
and remove from the back of sliding window.
15+
Time Complexity: O(N)
16+
Space Complexity: O(W) , W = length of Word
17+
18+
Solution 2: this can be solved using Rabin–Karp algorithm (small modification of this algorithm).
19+
But both solutions have same time & space complexity.
20+
'''
21+
22+
23+
############
24+
# Solution #
25+
############
26+
27+
class LettersCounter:
28+
def __init__(self):
29+
self.__letters = {}
30+
31+
def __create_if_not_exist(self, letter):
32+
''' helper method for creating a new field for the letter '''
33+
if letter not in self.__letters:
34+
self.__letters[letter] = 0
35+
36+
def __delete_if_zero_letters(self, letter):
37+
''' helper deleting a letter from dictionary '''
38+
if self.__letters[letter] == 0:
39+
del self.__letters[letter]
40+
41+
def add_letter(self, letter):
42+
''' increment the number of letters '''
43+
self.__create_if_not_exist(letter)
44+
self.__letters[letter] += 1
45+
self.__delete_if_zero_letters(letter)
46+
47+
def remove_letter(self, letter):
48+
''' decrement the number of letters '''
49+
self.__create_if_not_exist(letter)
50+
self.__letters[letter] -= 1
51+
self.__delete_if_zero_letters(letter)
52+
53+
def is_empty(self):
54+
return len(self.__letters) == 0
55+
56+
57+
def anagram_indicies(s, word):
58+
n = len(s)
59+
w = len(word)
60+
res = []
61+
62+
if n < w:
63+
return res
64+
65+
counter = LettersCounter()
66+
67+
# add all letters from the original word
68+
for letter in word:
69+
counter.add_letter(letter)
70+
71+
# remove first w letters from s string
72+
for i in range(w):
73+
counter.remove_letter(s[i])
74+
75+
if counter.is_empty():
76+
res.append(0)
77+
78+
for i in range(w, n):
79+
# continue with the same logic, add letters from front and remove from the current index
80+
counter.add_letter(s[i - w])
81+
counter.remove_letter(s[i])
82+
83+
if counter.is_empty():
84+
# if there are 0 elements into dictionary, then the word is anagram
85+
res.append(i - w + 1)
86+
87+
return res
88+
89+
90+
###########
91+
# Testing #
92+
###########
93+
94+
# correct result => [0, 3, 4]
95+
print(anagram_indicies('abxaba', 'ab'))

Strings/create_palindrome.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
'''
2+
Create Palindrome
3+
4+
Given a string, find the palindrome that can be made by inserting the fewest number of characters as possible anywhere in the word.
5+
If there is more than one palindrome of minimum length that can be made, return the lexicographically earliest one (the first one alphabetically).
6+
7+
Input: 'race'
8+
Output: 'ecarace'
9+
Output explanation: Since we can add three letters to it (which is the smallest amount to make a palindrome).
10+
There are seven other palindromes that can be made from "race" by adding three letters, but "ecarace" comes first alphabetically.
11+
12+
Input: 'google'
13+
Output: 'elgoogle'
14+
15+
=========================================
16+
Solution explanation
17+
Time Complexity: O(N) , The solution looks like O(N^2) but that's not possible
18+
Space Complexity: O(R) , R = length of the new word (you need to the old string and allocate memory for that)
19+
'''
20+
21+
22+
############
23+
# Solution #
24+
############
25+
26+
def create_palindrome(string):
27+
n = len(string)
28+
29+
# find the biggest left palindrome, which starts from the first letter
30+
max_left_palindrome = 1
31+
for i in reversed(range(1, n)):
32+
front = 0
33+
back = i
34+
found = True
35+
36+
while front <= back:
37+
if string[front] != string[back]:
38+
found = False
39+
break
40+
front += 1
41+
back -= 1
42+
43+
if found:
44+
max_left_palindrome = i + 1
45+
break
46+
47+
# find the biggest right palindrome, which starts from the last letter
48+
max_right_palindrome = 1
49+
for i in range(n - 1):
50+
front = i
51+
back = n - 1
52+
found = True
53+
54+
while front <= back:
55+
if string[front] != string[back]:
56+
found = False
57+
break
58+
front += 1
59+
back -= 1
60+
61+
if found:
62+
max_right_palindrome = n - i
63+
break
64+
65+
# reverse the string using [::-1]
66+
if max_right_palindrome > max_left_palindrome:
67+
return string + string[-max_right_palindrome - 1::-1]
68+
return string[:max_left_palindrome - 1:-1] + string
69+
70+
71+
###########
72+
# Testing #
73+
###########
74+
75+
# Test 1
76+
# correct result => 'ecarace'
77+
print(create_palindrome('race'))
78+
79+
# Test 2
80+
# correct result => 'elgoogle'
81+
print(create_palindrome('google'))

Strings/encoding_string.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
'''
2+
Encoding string
3+
4+
Run-length encoding is a fast and simple method of encoding strings.
5+
The basic idea is to represent repeated successive characters as a single count and character.
6+
Implement run-length encoding and decoding. You can assume the string to be encoded have no digits and consists solely of alphabetic characters.
7+
You can assume the string to be decoded is valid.
8+
9+
Input: 'AAAABBBCCDAA'
10+
Output: '4A3B2C1D2A'
11+
12+
=========================================
13+
Simple solution, just iterate the string and count.
14+
Time Complexity: O(N)
15+
Space Complexity: O(1)
16+
'''
17+
18+
19+
############
20+
# Solution #
21+
############
22+
23+
def encoding(word):
24+
n = len(word)
25+
if n == 0:
26+
return ''
27+
28+
letter = word[0]
29+
length = 1
30+
res = ''
31+
32+
for i in range(1, n):
33+
if word[i] == letter:
34+
length += 1
35+
else:
36+
res += str(length) + letter
37+
letter = word[i]
38+
length = 1
39+
40+
res += str(length) + letter
41+
42+
return res
43+
44+
45+
###########
46+
# Testing #
47+
###########
48+
49+
# correct result => '4A3B2C1D2A'
50+
print(encoding('AAAABBBCCDAA'))
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
'''
2+
Longest Substring With k Distinct Characters
3+
4+
Given an integer k and a string s, find the length of the longest substring that contains at most k distinct characters.
5+
6+
Input: s = 'abcba', k = 2
7+
Output: 'bcb'
8+
9+
=========================================
10+
Simple solution (like sliding window or queue, add to the end and remove from the front).
11+
Time Complexity: O(N)
12+
Space Complexity: O(N)
13+
'''
14+
15+
16+
############
17+
# Solution #
18+
############
19+
20+
def longest_substring_with_distinct_characters(s, k):
21+
letters = {}
22+
longest = 0
23+
length = 0
24+
25+
for i in range(len(s)):
26+
if s[i] in letters:
27+
# if this letter exists then only increase the counter and length
28+
letters[s[i]] += 1
29+
length += 1
30+
else:
31+
# if this letter doesn't exist then remove all discent letters from the front
32+
# so the count of discent letters will be k-1
33+
while len(letters) == k:
34+
firstLetter = s[i - length]
35+
letters[firstLetter] -= 1 # decrease the counter
36+
if letters[firstLetter] == 0:
37+
# remove this letter from the dictionary because
38+
# in the susbtring there are no letters like this
39+
del letters[firstLetter]
40+
length -= 1
41+
42+
# add the new letter in the dictionary
43+
letters[s[i]] = 1
44+
length += 1
45+
46+
# check if this length is the longest one
47+
longest = max(longest, length)
48+
49+
return longest
50+
51+
52+
###########
53+
# Testing #
54+
###########
55+
56+
# Test 1
57+
# correct result => 3
58+
print(longest_substring_with_distinct_characters('abcba', 2))
59+
60+
# Test 2
61+
# correct result => 8
62+
print(longest_substring_with_distinct_characters('abcbcbcbba', 2))
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
'''
2+
Longest Substring Without Repeating Characters
3+
4+
Given a string, find the length of the longest substring without repeating characters.
5+
6+
Input: 'abcabcbb'
7+
Output: 3
8+
Output explanation: The answer is 'abc', with the length of 3.
9+
10+
Input: 'bbbbb'
11+
Output: 1
12+
Output explanation: The answer is 'b', with the length of 1.
13+
14+
=========================================
15+
Simple string iteration, use hashset to save unique characters.
16+
If the current character exists in the set then move the left index till the one
17+
Time Complexity: O(N)
18+
Space Complexity: O(N)
19+
'''
20+
21+
22+
############
23+
# Solution #
24+
############
25+
26+
def length_of_longest_substring(s):
27+
unique_chars = set()
28+
max_length = 0
29+
left = 0
30+
n = len(s)
31+
32+
for i in range(n):
33+
while s[i] in unique_chars:
34+
# remove till the current char is unique
35+
unique_chars.remove(s[left])
36+
left += 1
37+
38+
# in this moment you're sure that the current char is unique
39+
unique_chars.add(s[i])
40+
max_length = max(max_length, i - left + 1)
41+
42+
return max_length
43+
44+
45+
###########
46+
# Testing #
47+
###########
48+
49+
# Test 1
50+
# correct result => 3
51+
print(length_of_longest_substring('abcabcbb'))
52+
53+
# Test 2
54+
# correct result => 1
55+
print(length_of_longest_substring('bbbbb'))
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'''
2-
Reverse words in sentence
2+
Reverse string
33
4-
Reverse words in a given string, in constant space and linear time complexity.
4+
Reverse string, in constant space and linear time complexity.
55
66
Input: 'i like this program very much' - In Python this should be a list (the string operations are slow/linear time)
77
Output: 'hcum yrev margorp siht ekil i'
@@ -40,11 +40,11 @@ def reverse_sentence(sentence):
4040
# Test 1
4141
s = ['i', ' ', 'l', 'i', 'k', 'e', ' ', 't', 'h', 'i', 's', ' ', 'p', 'r', 'o', 'g', 'r', 'a', 'm', ' ', 'v', 'e', 'r', 'y', ' ', 'm', 'u', 'c', 'h']
4242
reverse_sentence(s)
43-
# correct result = ['h', 'c', 'u', 'm', ' ', 'y', 'r', 'e', 'v', ' ', 'm', 'a', 'r', 'g', 'o', 'r', 'p', ' ', 's', 'i', 'h', 't', ' ', 'e', 'k', 'i', 'l', ' ', 'i']
43+
# correct result => ['h', 'c', 'u', 'm', ' ', 'y', 'r', 'e', 'v', ' ', 'm', 'a', 'r', 'g', 'o', 'r', 'p', ' ', 's', 'i', 'h', 't', ' ', 'e', 'k', 'i', 'l', ' ', 'i']
4444
print(s)
4545

4646
# Test 2
4747
s = ['h', 'o', 'w', ' ', 'a', 'r', 'e', ' ', 'y', 'o', 'u']
4848
reverse_sentence(s)
49-
# correct result = ['u', 'o', 'y', ' ', 'e', 'r', 'a', ' ', 'w', 'o', 'h']
49+
# correct result => ['u', 'o', 'y', ' ', 'e', 'r', 'a', ' ', 'w', 'o', 'h']
5050
print(s)

0 commit comments

Comments
 (0)