Skip to content

Commit 9a03843

Browse files
Meto TrajkovskiMeto Trajkovski
authored andcommitted
Added backtracking solutions
1 parent 7e42aeb commit 9a03843

6 files changed

Lines changed: 188 additions & 16 deletions

File tree

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
'''
2+
Generate Parentheses
3+
4+
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
5+
6+
Input: 3
7+
Output:
8+
[
9+
'((()))',
10+
'(()())',
11+
'(())()',
12+
'()(())',
13+
'()()()'
14+
]
15+
16+
=========================================
17+
This problem could be solved in several ways (using stack, queue, or just a simple list - see letter_combinations.py), all of them have the same complexity.
18+
I'll solve it using simple recursive algorithm.
19+
Time Complexity: O(4^N) , O(2^(2*N)) = O(2^N)
20+
Space Complexity: O(4^N)
21+
'''
22+
23+
24+
############
25+
# Solution #
26+
############
27+
28+
def generate_parentheses(n):
29+
result = []
30+
if n == 0:
31+
return result
32+
33+
combinations(result, n, n, '')
34+
35+
return result
36+
37+
38+
def combinations(result, open_left, close_left, combination):
39+
if close_left == 0:
40+
# a new combination is created (no more open or close parentheses)
41+
result.append(combination)
42+
elif open_left == 0:
43+
# no more open parentheses, so all left parentheses must be closed (just add the missing close parentheses)
44+
result.append(combination + (')' * close_left))
45+
else:
46+
combinations(result, open_left - 1, close_left, combination + '(')
47+
48+
# check if there is a pair for this close parenthesis
49+
if open_left < close_left:
50+
combinations(result, open_left, close_left - 1, combination + ')')
51+
52+
53+
###########
54+
# Testing #
55+
###########
56+
57+
# Test 1
58+
# Correct result => ['((()))', '(()())', '(())()', '()(())', '()()()']
59+
print(generate_parentheses(3))
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
'''
2+
Letter Combinations of a Phone Number
3+
4+
Given a string containing digits from 2-9 inclusive, return all possible letter combinations that the number could represent.
5+
A mapping of digit to letters is just like on the telephone buttons. Note that 1 does not map to any letters.
6+
7+
Input: '23'
8+
Output: ['ad', 'ae', 'af', 'bd', 'be', 'bf', 'cd', 'ce', 'cf']
9+
10+
=========================================
11+
This problem could be solved in several ways (using recursion, stack, queue...) and the complexity is same in all, but this one has the simplest code.
12+
Iterate all digits and in each step look for the previous combinations, create a new 3 or 4 combinations from each combination using the mapping letters.
13+
Time Complexity: O(3^N * 4^M) , N = number of digits that maps to 3 letters, M = number of digits that maps to 4 letters
14+
Space Complexity: O(3^N * 4^M)
15+
'''
16+
17+
18+
############
19+
# Solution #
20+
############
21+
22+
def letter_combinations(digits):
23+
if len(digits) == 0:
24+
return []
25+
26+
mappings = {
27+
'2': ['a','b','c'],
28+
'3': ['d','e','f'],
29+
'4': ['g','h','i'],
30+
'5': ['j','k','l'],
31+
'6': ['m','n','o'],
32+
'7': ['p','q','r','s'],
33+
'8': ['t','u','v'],
34+
'9': ['w','x','y','z']
35+
}
36+
prev_combinations = ['']
37+
38+
for digit in digits:
39+
new_combinations = []
40+
for combination in prev_combinations:
41+
# use the mappings and create new combinations
42+
for mapping in mappings[digit]:
43+
new_combinations.append(combination + mapping)
44+
# save the newest combinations
45+
prev_combinations = new_combinations
46+
47+
return prev_combinations
48+
49+
50+
###########
51+
# Testing #
52+
###########
53+
54+
# Test 1
55+
# Correct result => ['ad', 'ae', 'af', 'bd', 'be', 'bf', 'cd', 'ce', 'cf']
56+
print(letter_combinations('23'))

Backtracking/permutations.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
'''
2+
Permutations
3+
4+
Given a collection of distinct integers, return all possible permutations.
5+
6+
Input: [1,2,3]
7+
Output:
8+
[
9+
[1,2,3],
10+
[1,3,2],
11+
[2,1,3],
12+
[2,3,1],
13+
[3,1,2],
14+
[3,2,1]
15+
]
16+
17+
=========================================
18+
A classical recursive algorithm for permutations.
19+
Time Complexity: O(N!)
20+
Space Complexity: O(N!)
21+
'''
22+
23+
24+
############
25+
# Solution #
26+
############
27+
28+
def permutations(nums):
29+
result = []
30+
if len(nums) == 0:
31+
return result
32+
33+
permute(result, set(nums), [])
34+
35+
return result
36+
37+
def permute(result, nums, permutation):
38+
if len(nums) == 0:
39+
result.append([num for num in permutation])
40+
else:
41+
for num in list(nums): # create a new object with the same values because nums will be changed later
42+
nums.remove(num)
43+
permutation.append(num)
44+
45+
permute(result, nums, permutation)
46+
47+
# reset the structures
48+
del permutation[-1]
49+
nums.add(num)
50+
51+
52+
###########
53+
# Testing #
54+
###########
55+
56+
# Test 1
57+
# Correct result => [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
58+
print(permutations([1, 2, 3]))

Backtracking/power_set.py

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
'''
2-
The power set
2+
The Power Set
33
44
The power set of a set is the set of all its subsets.
55
Write a function that, given a set, generates its power set.
66
7-
Input: {1, 2, 3}
8-
Output: {{}, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}}
7+
Input: [1, 2, 3]
8+
Output: [[], [1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]]
99
* You may also use a list or array to represent a set.
1010
1111
=========================================
1212
Simple recursive combinations algorithm.
1313
Time Complexity: O(Sum(C(I, N))) , sum of all combinations between 0 and N = C(0, N) + C(1, N) + ... + C(N, N)
14-
Space Complexity: O(Sum(C(I, N))) , this is for the result array, if we print the number then the space complexity will be O(1)
14+
Space Complexity: O(Sum(C(I, N))) , this is for the result array, if we print the number then the space complexity will be O(N) (because of the recursive stack)
1515
'''
1616

1717

@@ -20,26 +20,24 @@
2020
############
2121

2222
def power_set(arr):
23-
return combinations(arr, [], 0)
24-
25-
# arr and taken are the same pointer always
26-
# the same arrays are used always
27-
def combinations(arr, taken, pos):
2823
result = []
29-
result.append([arr[i] for i in taken]) # create the current combination
24+
combinations(result, arr, [], 0)
25+
return result
3026

31-
if len(arr) == pos:
32-
return result
27+
# result, arr and taken are the same references always
28+
def combinations(result, arr, taken, pos):
29+
result.append([arr[i] for i in taken]) # create the current combination
3330

3431
n = len(arr)
32+
if n == pos:
33+
return
34+
3535
# start from the last position (don't need duplicates)
3636
for i in range(pos, n):
3737
taken.append(i)
38-
result += combinations(arr, taken, i + 1) # append the combinations
38+
combinations(result, arr, taken, i + 1)
3939
del taken[-1] # return to the old state
4040

41-
return result
42-
4341

4442
###########
4543
# Testing #

Backtracking/river_sizes.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
]
1818
Output: [2, 1, 3, 1]
1919
20-
2120
=========================================
2221
This problem can be solved using DFS or BFS.
2322
If 1 is found, find all horizontal or vertical neighbours (1s), and mark them as 0.

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ Solution 2 explanation
5151
Space Complexity: O(X)
5252
'''
5353

54+
5455
##############
5556
# Solution 1 #
5657
##############
@@ -59,6 +60,7 @@ def name_of_solution_1(params):
5960
# description of code
6061
pass
6162

63+
6264
##############
6365
# Solution 2 #
6466
##############

0 commit comments

Comments
 (0)