Combination Sum
Using backtracking we find all possible combinations of the collection that sum up to target.
def combination_sum(collection: list, target: int) -> list:
result = []
current = []
def backtrack(target, previous):
if target == 0:
result.append(current.copy())
return
for i in range(previous, len(collection)):
if target >= collection[i]:
current.append(collection[i])
backtrack(target-collection[i], i)
current.pop()
backtrack(target, 0)
return result
All Subsequences
Finds all posable unique subsequence within sequence
using backtracking.
def all_subsequences(sequence: list) -> list:
result = []
def backtrack(current, index):
if index == len(sequence):
result.append(current.copy())
return
backtrack(current, index+1)
current.append(sequence[index])
backtrack(current, index+1)
current.pop(0)
backtrack([], 0)
return result
All Permutations
This loops through all possible combinations making sure to keep the length the same as the input. It keeps track of the indexes used so it does not repeat indexes and it gets every possible combination.
def all_permutations(sequence: list) -> list:
result = []
seen = [0 for _ in range(len(sequence))]
def backtrack(i, current):
if i == len(sequence):
result.append(current.copy())
return
for j in range(len(sequence)):
if not seen[j]:
current.append(sequence[j])
seen[j] = True
backtrack(i+1, current)
current.pop()
seen[j] = False
backtrack(0, [])
return result
Generate Parentheses
Generate n
number of parentheses pairs.
def generate_parentheses(n: int) -> list:
result = []
def backtrack(num_open, num_closed, current):
if len(current) == 2 * n:
result.append(current)
return
if num_open < n:
backtrack(num_open + 1, num_closed, current + "(")
if num_closed < num_open:
backtrack(num_open, num_closed + 1, current + ")")
backtrack(0, 0, "")
return result
Sum of Subsets
Using backtracking it tests all combinations of number to get to the target sum.
def sum_of_subsets(numbers: list, target_sum: int) -> list:
result = []
def backtrack(i, path, remaining_sum):
if sum(path) > target_sum or (remaining_sum + sum(path)) < target_sum:
return
if sum(path) == target_sum:
result.append(path.copy())
return
for j in range(i, len(numbers)):
backtrack(j+1, [*path, numbers[j]], remaining_sum - numbers[j])
backtrack(0, [], sum(numbers))
return result
Power Sum
Finds the number of ways that needed_sum
can be expressed as the sum of number to the nth power
. Example: If needed_sum = 13
and power = 2
there is 1 way to get 13, 2^2 + 3^2 = 4 + 9 = 13
.
def power_sum(needed_sum: int, power: int) -> int:
result = 0
def backtrack(current_sum, current_num):
nonlocal result
if current_sum == needed_sum:
result += 1
return
next_num = current_num ** power
if current_sum + next_num <= needed_sum:
current_sum += next_num
backtrack(current_sum, current_num+1)
current_sum -= next_num
if next_num < needed_sum:
backtrack(current_sum, current_num+1)
backtrack(0, 1)
return result
Match Word Pattern
Checks to see if the input string matches the provided the word pattern.
def match_word_pattern(pattern: str, input_string: str) -> bool:
pattern_map = {}
string_map = {}
def backtrack(pattern_index: int, string_index: int) -> bool:
if pattern_index == len(pattern) and string_index == len(input_string):
return True
if pattern_index == len(pattern) or string_index == len(input_string):
return False
char = pattern[pattern_index]
if char in pattern_map:
mapped_str = pattern_map[char]
if input_string.startswith(mapped_str, string_index):
return backtrack(pattern_index + 1, string_index + len(mapped_str))
else:
return False
for end in range(string_index + 1, len(input_string) + 1):
sub_string = input_string[string_index:end]
if sub_string in string_map:
continue
pattern_map[char] = sub_string
string_map[sub_string] = char
if backtrack(pattern_index + 1, end):
return True
del pattern_map[char]
del string_map[sub_string]
return False
return backtrack(0, 0)