Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions Problem1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
## Problem1
# Subsets (https://leetcode.com/problems/subsets/)
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
"""
Time Complexity: O(N * 2^N)
- There are 2^N possible subsets for an array of size N.
- In the base case, creating a shallow copy of the path (using list(path)) takes O(N) time.

Space Complexity: O(N)
- The maximum depth of the recursion tree is N.
- The auxiliary `path` array stores at most N elements.
- Note: This does not include the O(N * 2^N) space required to hold the final result array.
"""
result = []

def helper(idx, path):
nonlocal result, nums

# Base case: We have made a choose/don't choose decision for every element.
# We reached the end of the array, so the current path is a valid subset.
if idx == len(nums):
result.append(list(path)) # Create a shallow copy to prevent reference mutation
return

# --- Recursive Logic (Backtracking) ---

# Option 1: Not Choose Case
# We skip the current element at 'idx' and move to the next element.
# The path remains unmodified.
helper(idx + 1, path)

# Option 2: Choose Case
# We include the current element at 'idx' in our subset path.
path.append(nums[idx])

# Explore all further possibilities with this element included.
helper(idx + 1, path)

# Backtrack: Remove the element we just added before returning to the previous
# level of the recursion tree, so it doesn't leak into other parallel branches.
path.pop()

# Start the recursion at index 0 with an empty current subset.
helper(0, [])

return result
60 changes: 60 additions & 0 deletions Problem2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
## Problem2

# Palindrome Partitioning(https://leetcode.com/problems/palindrome-partitioning/)
class Solution:
def partition(self, s: str) -> List[List[str]]:
"""
Time Complexity: O(N * 2^N)
- The Subsets (2^N): In the worst-case scenario where every substring is a palindrome
(e.g., "aaaa"), there are 2^(N-1) possible ways to partition the string.
- The Palindrome Check (N): For each of those possible partitions, we slice strings
and check if they are palindromes, taking O(N) time.
- Total: O(N * 2^N), where N is the length of string s.

Space Complexity: O(N)
- Recursion Stack: The maximum depth of the recursive call stack is N (happens when
partitioned into single characters).
- Path Variable: The 'path' array can hold a maximum of N strings at any given time.
- Total: O(N) + O(N) = O(N). (Note: This excludes the space required to store the
final 'result' array).
"""

# This will store all of our valid palindrome partitions
result = []

def helper(s, pivot, path):
nonlocal result
n = len(s)

# --- BASE CASE ---
# If our pivot reaches the end of the string (n), it means we have
# successfully partitioned the entire string into valid palindromes.
if pivot == n:
# We append a *copy* of the current path (using list()) because
# 'path' is a reference and will be modified by future recursive calls.
result.append(list(path))
return

# --- RECURSIVE LOGIC & BACKTRACKING ---
# We iterate through the string starting from our current 'pivot'.
# 'i' represents the ending index of the substring we are evaluating.
for i in range(pivot, n):
# Extract the current substring from pivot to i
curr = s[pivot:i+1]

# Check if the extracted substring is a palindrome
if curr == curr[::-1]:
# 1. CHOOSE: Add the valid palindrome to our current path
path.append(curr)

# 2. EXPLORE: Recursively partition the rest of the string.
# The new starting point (pivot) for the remaining string is i + 1.
helper(s, i + 1, path)

# 3. UN-CHOOSE (Backtrack): Remove the last added substring
# so we can continue the loop and try longer substrings from the original pivot.
path.pop()

# Kick off the recursion starting at index 0 with an empty path
helper(s, 0, [])
return result