Github Jakehoare Leetcode 4splits 75scale With Difficulty
Github Jakehoare Leetcode 4splits 75scale With Difficulty
return [] # no sum # Find the middle element if sum of input list lengths is odd, or else the average of the middle pair.
# get_kth_smallest recusively removes k//2 elements from one list.
# Time - O(log(m+n)), half of the elements smaller than median are removed each recursive call.
# Space - O(log(m+n)) for the recursive call stack.
# python_1_to_1000/002_Add_Two_Numbers.py - m
class Solution(object):
_author_ = 'jake' def findMedianSortedArrays(self, A, B):
_project_ = 'leetcode' """
:type A: List[int]
# https://leetcode.com/problems/add-two-numbers/ :type B: List[int]
# You are given two linked lists representing two non-negative numbers. :rtype: float
# The digits are stored in reverse order and each of their nodes contain a single digit. """
# Add the two numbers and return it as a linked list. def get_kth_smallest(a_start, b_start, k):
# Iterate over lists. Add to result a node with the the sum of input nodes plus carry, mod 10. if k <= 0 or k > len(A) - a_start + len(B) - b_start:
# Time - O(max(m,n)) where m and n are input list lengths. raise ValueError('k is out of the bounds of the input lists')
# Space - O(max(m,n)), output will be at most one digit more than longest input.
# base cases
# Definition for singly-linked list. if a_start >= len(A):
class ListNode(object): return B[b_start + k - 1]
def __init__(self, x): if b_start >= len(B):
self.val = x return A[a_start + k - 1]
self.next = None if k == 1:
return min(A[a_start], B[b_start])
class Solution(object):
def addTwoNumbers(self, l1, l2): # remove k//2 elements from one list
""" # find the smallest of the k//2 - 1th element from both lists and recurse having reduced that list.
:type l1: ListNode # k//2 - 1th element must exist in at least 1 list
:type l2: ListNode mid_A, mid_B = float('inf'), float('inf')
:rtype: ListNode if k // 2 - 1 < len(A) - a_start:
""" mid_A = A[a_start + k // 2 - 1]
prev = result = ListNode(None) # dummy head if k // 2 - 1 < len(B) - b_start:
carry = 0 mid_B = B[b_start + k // 2 - 1]
return result.next
# python_1_to_1000/005_Longest_Palindromic_Substring.py - m
# python_1_to_1000/003_Longest_Substring_Without_Repeating_Characters.py - m
_author_ = 'jake'
_author_ = 'jake' _project_ = 'leetcode'
_project_ = 'leetcode'
# https://leetcode.com/problems/longest-palindromic-substring/
# https://leetcode.com/problems/longest-substring-without-repeating-characters/ # Given a string S, find the longest palindromic substring in S.
# Given a string, find the length of the longest substring without repeating characters. # You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.
# Maintain a sliding window, updating the start whenever we see a character repeated. # For each centre point of a character or between 2 characters,
# Time - O(n) # expand the palindrome if the end characters are the same.
# Space - O(1), dictionary is limited by fixed size alphabet # Return early by starting with the middle centre and ruling out later centres that could not have longer
# substring than the palindrome already found.
# Time - O(n^2), 2n centres, each expanded upto n times # Example2: x = -123, return -321
# Space - O(n) to store the result
# Repeatedly multiply previous result by 10 and add last digit.
# Note that Manacher's algorithm provides a O(n) time solution. # Time - O(n) where n is the number of digits.
# Space - O(n), same number of digits in output as input.
class Solution(object):
def longestPalindrome(self, s): class Solution(object):
""" def reverse(self, x):
:type s: str """
:rtype: str :type x: int
""" :rtype: int
longest = "" """
negative = x < 0 # record if negative and change to positive
# create list of 2n-1 possible centres, each letter and between each pair x = abs(x)
# even indices represent letters, odd represent between letters reversed = 0
# start with middle index that potentially creates longest palindrome
centres = [len(s) - 1] while x != 0:
for diff in range(1, len(s)): # build list of indices from long to short reversed = reversed * 10 + x % 10
centres.append(centres[0] + diff) x //= 10
centres.append(centres[0] - diff)
if reversed > 2**31 - 1: # required to pass leetcode test cases, not applicable for python
for centre in centres: return 0
return reversed if not negative else -reversed
if (min(centre + 1, 2 * len(s) - 1 - centre) <= len(longest)):
break # return if cannot make a longer palindrome
if centre % 2 == 0:
left, right = (centre // 2) - 1, (centre // 2) + 1
else: # python_1_to_1000/008_String_to_Integer_(atoi).py - m
left, right = centre // 2, (centre // 2) + 1
_author_ = 'jake'
while left >= 0 and right < len(s) and s[left] == s[right]: _project_ = 'leetcode'
left -= 1
right += 1 # https://leetcode.com/problems/string-to-integer-atoi/
# left and right are now beyond the ends of the substring # Implement atoi to convert a string to an integer.
# Notes: It is intended for this problem to be specified vaguely (ie, no given input specs).
if right - left - 1 > len(longest): # You are responsible to gather all the input requirements up front.
longest = s[left + 1:right]
# Return the integer upto any non-digit.
return longest # Time - O(n)
# Space - O(n), new str created by strip()
while left < right: # Repeatedly take of as many copies of each numeral as possible until num is less than
if s[left] != s[right]: # the value of that numeral.
return False # Time - O(n) where n = len(str(num)), the longest roman equivalent is 8 where one digit maps to 4 chars
left += 1 # Space - O(n)
right -=1
class Solution(object):
return True def intToRoman(self, num):
"""
:type num: int
# python_1_to_1000/010_Regular_Expression_Matching.py - h :rtype: str
"""
_author_ = 'jake' mapping = [(1000, 'M'),
_project_ = 'leetcode' (900, 'CM'),
(500, 'D'),
# https://leetcode.com/problems/regular-expression-matching/ (400, 'CD'),
# Implement regular expression matching with support for '.' and '*'. (100, 'C'),
# '.' Matches any single character. (90, 'XC'),
# '*' Matches zero or more of the preceding element. (50, 'L'),
# The matching should cover the entire input string (not partial). (40, 'XL'),
(10, 'X'),
# Dynamic programming calculation of matrix of whether any prefix of s patches any prefix of p. (9, 'IX'),
# Time - O(m*n) when m = len(p) and n = len(s) (5, 'V'),
# Space - O(m*n) (4, 'IV'),
(1, 'I'),]
class Solution(object):
def isMatch(self, s, p): roman = []
for i, numeral in mapping:
# matched[i][j] is True if the first i chars of s (i.e. s[:i]) matches the first j chars of p (i.e. p[:j]) while num >= i:
matched = [[False for _ in range(len(p)+1)] for _ in range(len(s)+1)] num -= i
matched[0][0] = True # no pattern (j=0) matches no string and not any non-zero string roman.append(numeral)
# Start with the widest separation of lines. To form a greater area, any lesser separation must have a greater integer = 0
# minimum boundary height. i = 0
# Time - O(n) while i < len(s):
# Space - O(1) if i < len(s) - 1 and s[i:i + 2] in doubles:
integer += doubles[s[i:i + 2]]
class Solution(object): i += 2
def maxArea(self, height): else:
""" integer += singles[s[i]]
:type height: List[int] i += 1
:rtype: int
""" return integer
left = 0
right = len(height)-1
max_area = (right - left) * min(height[right], height[left])
# python_1_to_1000/014_Longest_Common_Prefix.py
while left < right:
if height[left] < height[right]: # By moving in the lower boundary we have the possibility _author_ = 'jake'
left += 1 # of finding a larger area. _project_ = 'leetcode'
else:
right -= 1 # https://leetcode.com/problems/longest-common-prefix/
max_area = max(max_area, (right - left) * min(height[right], height[left])) # Write a function to find the longest common prefix string amongst an array of strings.
return max_area # Sort strings and find longest prefix of first and last, which are the most different.
# Alternatively all strings could be inserted into a trie and we find the first node
# with more than one child.
# python_1_to_1000/012_Integer_to_Roman.py - m # Time - O(k*n logn) where k is the length of the longest string and n is number of strings.
# Space - O(1)
_author_ = 'jake'
_project_ = 'leetcode' class Solution(object):
def longestCommonPrefix(self, strs):
# https://leetcode.com/problems/integer-to-roman/ """
# Given an integer, convert it to a roman numeral. :type strs: List[str]
# Sort the array. For each index i perform a bidirectional search on the higher values in the array.
# Skip over duplicates. Increment i to the next new minimum number. # python_1_to_1000/017_Letter_Combinations_of_a_Phone_Number.py - m
# Time - O(n**2), for each i at least one of j and k moves every iteration.
# Space - O(n) _author_ = 'jake'
_project_ = 'leetcode'
class Solution(object):
def threeSum(self, nums): # https://leetcode.com/problems/letter-combinations-of-a-phone-number/
""" # Given a digit string, return all possible letter combinations that the number could represent.
:type nums: List[int]
:rtype: List[List[int]] # For each digit add all possible letter mappings to each of the previous results.
""" # Alternatively can be solved recursively.
results = [] # Time - O(n * 4^n)
nums.sort() # Space - O(n * 4^n), max 4 possible chars per digit so O(4^n) strings each of length n
i = 0 class Solution(object):
while i < len(nums): def letterCombinations(self, digits):
j = i + 1 """
k = len(nums) - 1 :type digits: str
:rtype: List[str]
while j < k: """
if not digits or '0' in digits or '1' in digits:
triple_sum = nums[i] + nums[j] + nums[k] return []
if triple_sum == 0: # record result and move both j and k to next new numbers results = [[]]
results.append([nums[i], nums[j], nums[k]]) mapping = {'2' : ['a', 'b', 'c'],
k -= 1 '3' : ['d', 'e', 'f'],
while k > j and nums[k] == nums[k + 1]: '4' : ['g', 'h', 'i'],
k -= 1 '5' : ['j', 'k', 'l'],
j += 1 '6' : ['m', 'n', 'o'],
while j < k and nums[j] == nums[j - 1]: '7' : ['p', 'q', 'r', 's'],
j += 1 '8' : ['t', 'u', 'v'],
'9' : ['w', 'x', 'y' , 'z']}
elif triple_sum > 0: # decrement k to next new number
k -= 1 for digit in digits:
while k > j and nums[k] == nums[k + 1]: temp = []
k -= 1 for result in results:
else: # increment j to next new number for letter in mapping[digit]:
j += 1 temp.append(result + [letter])
while j < k and nums[j] == nums[j - 1]: results = temp
j += 1
# convert lists of chars to strings
i += 1 # increment i to next new number return ["".join(result) for result in results]
while i < len(nums) - 2 and nums[i] == nums[i - 1]:
i += 1
# python_1_to_1000/018_4Sum.py - m
return results
_author_ = 'jake'
_project_ = 'leetcode'
# https://leetcode.com/problems/4sum/
# python_1_to_1000/016_3Sum_Closest.py - m # Given an array nums of n integers, are there elements a, b, c, and d in nums such that a + b + c + d = target?
# Find all unique quadruplets in the array which gives the sum of target.
_author_ = 'jake' # Note: The solution set must not contain duplicate quadruplets.
_project_ = 'leetcode'
# Recursively reduce to 2sum problem.
# https://leetcode.com/problems/3sum-closest/ # Time - O(n^3), for each pair perform linear search on the rest of the array
# Given an array nums of n integers, find three integers in nums such that the sum is closest to a given number, target.
# Return the sum of the three integers. You may assume that each input would have exactly one solution. class Solution(object):
ELEMENTS = 4 # parametrise the number of elements being summed
# Sort the array. For each staring index bidirectional search in the rest of the array.
# Time - O(n**2) def fourSum(self, nums, target):
# Space - O(1) """
:type nums: List[int]
class Solution(object): :type target: int
def threeSumClosest(self, nums, target): :rtype: List[List[int]]
""" """
:type nums: List[int] results = []
self.n_sum(sorted(nums), target, [], self.ELEMENTS, results) for c in s:
return results if c in match:
stack.append(c)
else:
def n_sum(self, nums, target, partial, n, results): # generalise for n-sum if not stack or match[stack.pop()] != c:
return False
if len(nums) < n or target > nums[-1]*n or target < nums[0]*n: # early return if impossible
return return not stack
class Solution(object):
# python_1_to_1000/019_Remove_Nth_Node_From_End_of_List.py - m def mergeTwoLists(self, l1, l2):
_author_ = 'jake' prev = dummy = ListNode(None) # new dummy head for the merged list
_project_ = 'leetcode'
while l1 and l2: # link prev to the lowest node
# https://leetcode.com/problems/remove-nth-node-from-end-of-list/
# Given a linked list, remove the nth node from the end of list and return its head. if l1.val < l2.val:
prev.next = l1
# Advance first pointer n steps then advance both pointers at same rate. l1 = l1.next
# Time - O(n) else:
# Space - O(1) prev.next = l2
l2 = l2.next
# Definition for singly-linked list.
# class ListNode(object): prev = prev.next
# def __init__(self, x):
# self.val = x prev.next = l1 or l2 # link prev to the list with remaining nodes
# self.next = None return dummy.next
class Solution(object):
def removeNthFromEnd(self, head, n):
"""
:type head: ListNode # python_1_to_1000/022_Generate_Parentheses.py - m
:type n: int
:rtype: ListNode _author_ = 'jake'
""" _project_ = 'leetcode'
first, second = head, head
# https://leetcode.com/problems/generate-parentheses/
for i in range(n): # move first n steps forwards # Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
first = first.next
if not first: # Recursively add an opening left bracket if any remain, and a closing right bracket if more left brackets have been
return head.next used.
# Time - O(2^n), each recursion can generate 2 recursive calls althougn in practive this is an upper bound
while first.next: # move both pointers until first is at end # Space - O(2^n)
first = first.next
second = second.next class Solution(object):
second.next = second.next.next # nth from end is second.next def generateParenthesis(self, n):
return head """
:type n: int
:rtype: List[str]
# python_1_to_1000/020_Valid_Parentheses.py """
result = []
_author_ = 'jake' self.generate([], n, n, result)
_project_ = 'leetcode' return result
# https://leetcode.com/problems/valid-parentheses/ # Generates all parentheses given a starting prefix and remaining left and right brackets.
# Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. def generate(self, prefix, left, right, result):
# The brackets must close in the correct order, "()" and "()[]{}" are all valid but "(]" and "([)]" are not. if left == 0 and right == 0:
result.append("".join(prefix))
# Maintain a stack of opening brackets. For each closing bracket pop the head of the stack and check it matches. if left != 0:
# Time - O(n) self.generate(prefix + ['('], left-1, right, result)
# Space - O(n) if right > left:
self.generate(prefix + [')'], left, right-1, result)
class Solution(object):
def isValid(self, s):
"""
:type s: str
:rtype: bool # python_1_to_1000/023_Merge_k_Sorted_Lists.py - h
"""
stack = [] _author_ = 'jake'
match = {'(' : ')', '[' : ']', '{' : '}'} _project_ = 'leetcode'
# https://leetcode.com/problems/merge-k-sorted-lists/ # You may not alter the values in the nodes, only nodes itself may be changed.
# Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. # Only constant memory is allowed.
# Maintain a min heap of tuples of (val, list index) for the next node in each list. # If there are at least k nodes, recursively reverse remainder and append reversed group to reversed remainder.
# Also maintain a list of the next node to be merged for each list index. # Time - O(n)
# Time - O(n log k) for n total nodes, each of which is pushed and popped from heap in log k time. # Space - O(1)
# Space - O(k) for heap of k nodes
class Solution(object):
# Definition for singly-linked list. def reverseKGroup(self, head, k):
class ListNode(object): """
def __init__(self, x): :type head: ListNode
self.val = x :type k: int
self.next = None :rtype: ListNode
"""
import heapq if k < 2:
return head
class Solution(object):
def mergeKLists(self, lists): node = head
""" for _ in range(k):
:type lists: List[ListNode] if not node:
:rtype: ListNode return head # return head if there are not at least k nodes
""" node = node.next
prev = dummy = ListNode(None) # else node is now head of second group
next_nodes, heap = [], []
# reverse remainder after this group
for i, node in enumerate(lists): prev = self.reverseKGroup(node, k)
next_nodes.append(node) # next_nodes[i] is the next node to be merged from lists[i]
if node: for _ in range(k): # reverse this group, adding in front of prev
heap.append((node.val, i)) temp = head.next
heapq.heapify(heap) head.next = prev
prev = head
while heap: head = temp
value, i = heapq.heappop(heap)
node = next_nodes[i] return prev
prev.next = node # add node to merged list
prev = prev.next
if node.next: # python_1_to_1000/026_Remove_Duplicates_from_Sorted_Array.py
next_nodes[i] = node.next
heapq.heappush(heap, (node.next.val, i)) _author_ = 'jake'
_project_ = 'leetcode'
return dummy.next
# https://leetcode.com/problems/remove-duplicates-from-sorted-array/
# Given a sorted array, remove the duplicates in place such that each element appear only once and return the new
length.
# python_1_to_1000/024_Swap_Nodes_in_Pairs.py - m # Do not allocate extra space for another array, you must do this in place with constant memory.
_author_ = 'jake' # Maintain a pointer to the next index to be filled with a new number. Check every number against the previous num
_project_ = 'leetcode' # (if any) and if different, move to the next_new index.
# Time - O(n)
# https://leetcode.com/problems/swap-nodes-in-pairs/ # Space - O(1)
# Given a linked list, swap every two adjacent nodes and return its head.
# E.g. given 1->2->3->4, you should return the list as 2->1->4->3. class Solution(object):
# Your algorithm should use only constant space. You may not modify the values in the list, only nodes itself can be def removeDuplicates(self, nums):
changed. """
:type nums: List[int]
# Store the previous node, swap and append in pairs. :rtype: int
# Time - O(n) """
# Space - O(1) next_new = 0 # index where the next unique number is to be moved to
while dividend >= (max_divisor << 1): # find divisor * 2^i where divisor * 2^(i+1) > dividend class Solution(object):
max_divisor <<= 1 def nextPermutation(self, nums):
shift_count <<= 1 """
:type nums: List[int]
while shift_count >= 1: :rtype: void Do not return anything, modify nums in-place instead.
if dividend >= max_divisor: # subtract max_divisor whenever possible """
dividend -= max_divisor if not nums or len(nums) == 1:
result += shift_count return
shift_count >>= 1
max_divisor >>= 1 i = len(nums)-2 # starting at back, find the first decrease - increasing it will increment the permutation
while i >= 0 and nums[i] >= nums[i+1]:
if diff_sign: i -= 1
result = -result
return max(min(result, 2**31-1), -2**31) # required for leetcode if i != -1: # if any decrease then find the smallest larger number to swap with
j = i+1
while j < len(nums) and nums[j] > nums[i]:
j += 1
# python_1_to_1000/030_Substring_with_Concatenation_of_All_Words.py - h j -= 1
nums[i], nums[j] = nums[j], nums[i]
_author_ = 'jake'
_project_ = 'leetcode' # reverse all from i+1 onwards since they were decreasing and increasing minimises permutation
left = i+1
# https://leetcode.com/problems/substring-with-concatenation-of-all-words/ right = len(nums)-1
# You are given a string, s, and a list of words, words, that are all of the same length. while left < right:
# Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once nums[left], nums[right] = nums[right], nums[left]
# and without any intervening characters. left += 1
right -= 1
_author_ = 'jake'
_project_ = 'leetcode'
# python_1_to_1000/032_Longest_Valid_Parentheses.py - h # https://leetcode.com/problems/search-for-a-range
# Given a sorted array of integers, find the starting and ending position of a given target value.
_author_ = 'jake' # Your algorithm's runtime complexity must be in the order of O(log n).
_project_ = 'leetcode' # If the target is not found in the array, return [-1, -1].
# https://leetcode.com/problems/longest-valid-parentheses/ # Search for target +/- 0.5 (not integer so not found) and return the index above this.
# Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) # If same index is returned for + and - 0.5 then target not found.
parentheses substring. # Binary search could be implemented iteratively or use the bisect module.
# For example is ")()())", where the longest valid parentheses substring is "()()", which has length = 4. # Time - O(log n)
# Space - O(1)
# Maintain a stack of indices in s of unmatched brackets. Pop an opening bracket when matched with a closing bracket.
# Push unmatched closing brackets and all opening brackets. Then find the longest gap between indices on the stack. class Solution(object):
# Time - O(n) def searchRange(self, nums, target):
# Space - O(n) """
:type nums: List[int]
class Solution(object): :type target: int
def longestValidParentheses(self, s): :rtype: List[int]
""" """
:type s: str def binary(target, left, right):
:rtype: int
""" if left > right:
stack = [] # indices of brackets that are not matched return left
stack.append(len(s)) # last unmatched index after end of s return binary(target, left, right)
max_length = stack[0] # first unmatched index before start of s
lower = binary(target - 0.5, 0, len(nums) - 1)
for index in range(1, len(stack)): # find max gap between remaining unmatched indices upper = binary(target + 0.5, 0, len(nums) - 1)
max_length = max(max_length, stack[index] - stack[index-1] - 1) return [-1, -1] if lower == upper else [lower, upper - 1]
return max_length
# python_1_to_1000/035_Search_Insert_Position.py
_author_ = 'jake'
# python_1_to_1000/033_Search_in_Rotated_Sorted_Array.py - m _project_ = 'leetcode'
class Solution(object):
# python_1_to_1000/034_Search_for_a_Range.py - m def isValidSudoku(self, board):
"""
:type board: List[List[str]] for r in range(self.size):
:rtype: bool for c in range(self.size):
"""
size = 9 if len(self.board[r][c]) == 1:
digits = {str(i) for i in range(1,10)} continue
rows = [set() for _ in range(size)] for digit in self.board[r][c]: # loop over possible digits
cols = [set() for _ in range(size)] if self.is_valid(r, c, digit): # will always be valid on first recursion
boxes = [set() for _ in range(size)] save_set = self.board[r][c]
self.board[r][c] = digit
for r in range(size): if self.solve_recursive():
for c in range(size): return True
self.board[r][c] = save_set # revert back
digit = board[r][c] return False
if digit == '.': return True
continue
if digit not in digits: def is_valid(self, row, col, digit): # checks whether board is valid after adding digit in row, col
return False for i in range(self.size): # row and column
if self.board[row][i] == digit or self.board[i][col] == digit:
box = (size//3) * (r // (size//3)) + (c // (size//3)) return False
if digit in rows[r] or digit in cols[c] or digit in boxes[box]:
return False n = self.size // 3
rows[r].add(digit) for r in range(n*(row//n), n + n*(row//n)): # box
cols[c].add(digit) for c in range(n*(col//n), n + n*(col//n)):
boxes[box].add(digit) if self.board[r][c] == digit:
return False
return True return True
# python_1_to_1000/037_Sudoku_Solver.py - h
# python_1_to_1000/038_Count_and_Say.py - m
_author_ = 'jake'
_project_ = 'leetcode' _author_ = 'jake'
_project_ = 'leetcode'
# https://leetcode.com/problems/sudoku-solver/
# Write a program to solve a Sudoku puzzle by filling the empty cells. # https://leetcode.com/problems/count-and-say/
# Empty cells are indicated by the character '.'. # The count-and-say sequence is the sequence of integers beginning as follows:
# You may assume that there will be only one unique solution. # 1, 11, 21, 1211, 111221, ...
# 21 is read off as "one 2, then one 1" or 1211.
# Convert unknown cells to a set of possible digits, initially {1..9}. # Given an integer n, generate the nth sequence.
# Repeatedly use known cells to eliminate possibilities in unknown cells. Which creates new known cells etc.
# If this does not result in a solution, recursively guess each cell from its range of possibilities. # Iterate through the previous sequence. When we see a different number, append [1, num] to the new sequence.
# When we see the same number increment its count.
class Solution(object): # Time - O(2^n), the sequence at worst doubles each step
def solveSudoku(self, board): # Space - O(2^n)
"""
:type board: List[List[str]] class Solution(object):
:rtype: void Do not return anything, modify board in-place instead. def countAndSay(self, n):
""" """
self.size = 9 :type n: int
self.board = board :rtype: str
self.new_digits = [] # new digits at start or digits found by reducing to 1 possibility """
sequence = [1]
for r in range(self.size): for _ in range(n-1):
self.board[r] = [digit for digit in self.board[r]] # convert from string to list of digits next = []
for c in range(self.size): for num in sequence:
if self.board[r][c] == '.': if not next or next[-1] != num:
self.board[r][c] = {str(i) for i in range(1, 10)} # convert dot to set of possible digits next += [1, num]
else: else:
self.new_digits.append((r, c)) next[-2] += 1
sequence = next
while self.new_digits:
for r, c in self.new_digits: return "".join(map(str, sequence))
self.eliminate(r, c) # given a new digit in (r,c), eliminate that digit from row, col and box
self.new_digits = []
self.find_new() # identify cells with only one possible digit
self.solve_recursive() # python_1_to_1000/039_Combination_Sum.py - m
_author_ = 'jake'
def eliminate(self, row, col): _project_ = 'leetcode'
for i in range(self.size):
# https://leetcode.com/problems/combination-sum/
if isinstance(self.board[i][col], set): # Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate
self.board[i][col].discard(self.board[row][col]) # discard does not cause error if element not present numbers sums to T.
if isinstance(self.board[row][i], set): # The same repeated number may be chosen from C unlimited number of times.
self.board[row][i].discard(self.board[row][col]) # All numbers (including target) will be positive integers.
# The solution set must not contain duplicate combinations.
for box_row in range(3*(row//3), 3 + 3*(row//3)):
for box_col in range(3*(col//3), 3 + 3*(col//3)): # Subtract each candidate from target as many times as possible whilst remainder is non-negative. Recurse
if isinstance(self.board[box_row][box_col], set): # each time, moving on to the next candidate.
self.board[box_row][box_col].discard(self.board[row][col]) # Time - approx f^n where f is target/average_candidate and n is the number of candidates with this nb recursions
return result # Your algorithm should run in O(n) time and uses constant space
def helper(self, nums, next, target, partial, result): # If an element of nums is a positive integer that could appear in nums (1 to len(nums) inclusive) and is not in
if target == 0: # correct place (nums[i] = i+1) then swap.
result.append(partial) # Time - O(n)
return # Space - O(1)
if next == len(nums):
return class Solution(object):
def firstMissingPositive(self, nums):
i = 0 """
while target - i * nums[next] >= 0: :type nums: List[int]
self.helper(nums, next + 1, target - i * nums[next], partial + [nums[next]] * i, result) :rtype: int
i += 1 """
i = 0
while i < len(nums):
# python_1_to_1000/040_Combination_Sum_II.py - m while nums[i] > 0 and nums[i] <= len(nums) and nums[nums[i]-1] != nums[i]:
temp = nums[nums[i]-1]
_author_ = 'jake' nums[nums[i]-1] = nums[i]
_project_ = 'leetcode' nums[i] = temp
# https://leetcode.com/problems/combination-sum-ii/ i += 1
# Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the
candidate numbers sums to T. for i, num in enumerate(nums):
# Each number in C may only be used once in the combination. if nums[i] != i+1:
# All numbers (including target) will be positive integers. return i+1
# The solution set must not contain duplicate combinations. return len(nums)+1
# Count the frequency of each number in candidates. For each number subtract all possible numbers of copies up to
# the count and without exceeding target and recurse for the next number. Alternative iterative version below.
# Time - O((f+1)^n) where f is the max frequency of any number and n is the number of distinct numbers # python_1_to_1000/042_Trapping_Rain_Water.py - h
new_partials = [] # https://leetcode.com/problems/multiply-strings/
for partial in partials: # Given two numbers represented as strings, return multiplication of the numbers as a string.
# The numbers can be arbitrarily large and are non-negative.
partial_sum = sum(partial) # Converting the input string to integer is NOT allowed.
for i in range(count + 1): # You should NOT use internal library such as BigInteger.
if partial_sum + candidate*i < target:
new_partials.append(partial + [candidate]*i) # Create a list of each digit in the result, starting wiht the least significant digit.
elif partial_sum + candidate*i == target: # Reverse input digit order. nums1[i] * nums2[j] is added to result[i+j+1] and result[i+j]
results.append(partial + [candidate]*i) # Alternatively: return str(int(num1) * int(num2))
if partial_sum + candidate*i >= target: # Time - O(m * n) where inputs are of lengths m and n
break # Space - O(max(m,n))
# https://leetcode.com/problems/first-missing-positive/
# Given an unsorted integer array, find the first missing positive integer. for i in range(len(num1)):
# e.g. given [1,2,0] return 3, and [3,4,-1,1] return 2.
int1 = ord(num1[i]) - ord('0') class Solution(object):
def jump(self, nums):
for j in range(len(num2)): """
:type nums: List[int]
int2 = ord(num2[j]) - ord('0') :rtype: int
"""
tens, units = divmod(int1 * int2, 10) if len(nums) == 1:
return 0
result[i + j] += units # add units and handle carry of units
if result[i + j] > 9: start, end = 0, 0 # indices in nums of current range
result[i + j + 1] += result[i + j] // 10 max_index = 0
result[i + j] %= 10 steps = 1
result[i + j + 1] += tens # add tens and handle carry of tens while True: # will always terminate since last index is accessible
if result[i + j + 1] > 9: for i in range(start, end+1):
result[i + j + 2] += result[i + j + 1] // 10 max_index = max(max_index, i + nums[i])
result[i + j + 1] %= 10 if max_index >= len(nums)-1:
return steps
while len(result) > 1 and result[-1] == 0: # remove trailing zeros steps += 1
result.pop() start, end = end + 1, max_index
return "".join(map(str, result[::-1])) # reverse and convert to string
# python_1_to_1000/046_Permutations.py - m
# python_1_to_1000/044_Wildcard_Matching.py - m
_author_ = 'jake'
_author_ = 'jake' _project_ = 'leetcode'
_project_ = 'leetcode'
# https://leetcode.com/problems/permutations/
# https://leetcode.com/problems/wildcard-matching/ # Given a collection of distinct numbers, return all possible permutations.
# Implement wildcard pattern matching with support for '?' and '*'.
# '?' Matches any single character. # For each number, insert it at all possible places in all existing permutations.
# '*' Matches any sequence of characters (including the empty sequence). # Alternatively recursively swap every index with every greater index (and itself).
# The matching should cover the entire input string (not partial). # Time - O(n^2 * n!). n! results, each of with has n elements added, each addition taking O(n) time for list slicing
# Space - O(n *n!)
# Record index in p of star and index in s at that time. Try to match without star, if fails back up and use *
# to match one more character from s. class Solution(object):
# Time - O(m * n), * at beginning of p could match many chars in s before failing and repeatedly backtrack def permute(self, nums):
# Space - O(1) """
:type nums: List[int]
class Solution(object): :rtype: List[List[int]]
def isMatch(self, s, p): """
permutations = [[]]
i, j = 0, 0 # next indices to be matched in s and p
star = -1 # last index in p of * for num in nums:
new_permutations = []
while i < len(s): for perm in permutations:
for i in range(len(perm) + 1):
# if beyond end of pattern or pattern is unmatched letter new_permutations.append(perm[:i] + [num] + perm[i:])
if j >= len(p) or (p[j] not in {'*' , '?'} and p[j] != s[i]): permutations = new_permutations
if star == -1: # no flexibility if no star
return False return permutations
j = star + 1 # reset p to character after star
star_i += 1 # reset s to charcater after star_i, i.e. use * to match one char from s
i = star_i class Solution2(object):
def permute(self, nums):
elif p[j] == '*': # record * index in p and next index to be matched in s """
star = j :type nums: List[int]
star_i = i :rtype: List[List[int]]
j += 1 """
return self.permute_helper(nums, 0)
else: # chars match or ?, increment both
i += 1 def permute_helper(self, nums, index):
j += 1
permutations = []
while j < len(p): # any remaining characters in p can only be *
if p[j] != '*': if index >= len(nums):
return False permutations.append(nums[:]) # make a new copy to freeze nums
j += 1
return True for i in range(index, len(nums)):
nums[i], nums[index] = nums[index], nums[i] # swap with all indices >= index
permutations += self.permute_helper(nums, index + 1)
nums[i], nums[index] = nums[index], nums[i] # swap back
_author_ = 'jake'
_project_ = 'leetcode'
# https://leetcode.com/problems/jump-game-ii/
# Given an array of non-negative integers, you are initially positioned at the first index of the array.
# Each element in the array represents your maximum jump length at that position.
# Your goal is to reach the last index in the minimum number of jumps. # python_1_to_1000/047_Permutations_II.py - m
# The minimum number of jumps to reach the last index is 2. (Jump 1 step from index 0 to 1, then 3 steps to the last
index.) _author_ = 'jake'
# You can assume that you can always reach the last index. _project_ = 'leetcode'
# For each index in currently accessible range, update the max_index that can be reached in one more step. # https://leetcode.com/problems/permutations-ii/
# Iterate to next range, from end of previous range to max_index. # Given a collection of numbers that might contain duplicates, return all possible unique permutations.
# Time - O(n)
# Space - O(1) # Count occurences of each unique number. Recursively append each number if still has a positive count.
# Time - O(n^2 * n!), as 046_Permutations if all numbers are unique
class Solution(object):
# python_1_to_1000/054_Spiral_Matrix.py - m def merge(self, intervals):
"""
_author_ = 'jake' :type intervals: List[Interval]
_project_ = 'leetcode' :rtype: List[Interval]
"""
# https://leetcode.com/problems/spiral-matrix/ intervals.sort(key=lambda x : x[0])
# Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order. merged = []
# Use row_leg and col_leg to traxk the max number of moves before turning. Decrease row_leg and col_leg then turning. for interval in intervals:
# Time - O(m * n) if not merged or merged[-1][1] < interval[0]:
# Space - O(1) merged.append(interval)
else:
class Solution(object): merged[-1][1] = max(merged[-1][1], interval[1])
def spiralOrder(self, matrix): return merged
"""
:type matrix: List[List[int]]
:rtype: List[int]
""" # python_1_to_1000/057_Insert_Intervals.py - m
if not matrix or not matrix[0]:
return [] _author_ = 'jake'
_project_ = 'leetcode'
spiral = []
row, col = 0, -1 # https://leetcode.com/problems/insert-interval/
d_row, d_col = 0, 1 # movement direction # Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary).
row_leg, col_leg = len(matrix[0]), len(matrix)-1 # steps before change of direction # You may assume that the intervals were initially sorted according to their start times.
row += d_r
# Find all intervals strictly to the left and to the right of new interval. If any intervals in between they col += d_c
# overlap with newInterval. If any overlap, update start of newInterval with start of first overlap and
# update end with end of last overlap. return spiral
# Time - O(n)
# Space - O(1)
while right >= 0 and intervals[right][0] > newInterval[1]: # Find each digit according to the ratio between k and the total number of possible permutations.
right -= 1 # Time - O(n**2) since each iteration adds one digit and O9n) for del from list
# Space - O(n) to store chars list
if left <= right:
newInterval[0] = min(newInterval[0], intervals[left][0]) from math import factorial
newInterval[1] = max(newInterval[1], intervals[right][1])
class Solution(object):
return intervals[:left] + [newInterval] + intervals[right + 1:] def getPermutation(self, n, k):
"""
:type n: int
:type k: int
# python_1_to_1000/058_Length_of_Last_Word.py :rtype: str
"""
_author_ = 'jake' chars = [str(i) for i in range(1, n+1)] # the symbols that will be permuted
_project_ = 'leetcode' permutations = factorial(n) # total number of permutations for this n
k -= 1 # change indexing to 0
# https://leetcode.com/problems/length-of-last-word/ result = []
# Given a string s consists of upper/lower-case alphabets and empty space characters ' ',
# return the length of last word in the string. while chars:
# If the last word does not exist, return 0. digit = n * k // permutations # get the first digit (range is 0 to n-1)
# Note: A word is defined as a character sequence consists of non-space characters only. result.append(chars[digit]) # map from digit to a symbol
del chars[digit] # remove that symbol
# Start at last character and decrement i. permutations //= n # repeat for next digit with decreased permutations, n and k
# Set variable end when non-blank is seen. k -= digit * permutations
# Return at next non-blank. n -= 1
# Time - O(n)
# Space - O(1) return "".join(result)
class Solution(object):
def lengthOfLastWord(self, s):
""" # python_1_to_1000/061_Rotate_List.py - m
:type s: str
:rtype: int _author_ = 'jake'
""" _project_ = 'leetcode'
i = len(s) - 1
end = -1 # https://leetcode.com/problems/rotate-list/
# Given a list, rotate the list to the right by k places, where k is non-negative.
while i >= 0:
if s[i] == ' ' and end != -1: # Count length of list, reset k to k % length (avoids repeated cycles). Connect tail of list with head and then
return end - i # break k%length steps before the old tail.
if s[i] != ' ' and end == -1: # Time - O(n), n is length of list
end = i # Space - O(1)
i -= 1
return end + 1 if end != -1 else 0 # Definition for singly-linked list.
class ListNode(object):
def __init__(self, x):
self.val = x
# python_1_to_1000/059_Spiral_Matrix_II.py - m self.next = None
# python_1_to_1000/062_Unique_Paths.py - m # Dynamic programming, min path to a cell = cell value + min(min paths to cells above and left)
# Time - O(m * n)
_author_ = 'jake' # Space - O(n)
_project_ = 'leetcode'
class Solution(object):
# https://leetcode.com/problems/unique-paths/ def minPathSum(self, grid):
# A robot is located at the top-left corner of a m x n grid. """
# The robot can only move either down or right at any point in time. :type grid: List[List[int]]
# The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below). :rtype: int
# How many possible unique paths are there? """
m = len(grid)
# Dynamic programming, nb paths = paths from above cell + paths from right cell n = len(grid[0])
# Alternatively, catalan number.
# Time - O(m * n) min_path = [float('inf') for _ in range(n + 1)]
# Space - O(n), just keep last row instead of entire grid min_path[1] = 0
# Dynamic programming. Nb paths is 0 if obstacle, else paths from above + paths from left. def is_int(self, s, signed):
# Time - O(m * n) if len(s) == 0:
# Space - O(n) return False
if s[0] == '-' and signed:
class Solution(object): s = s[1:]
def uniquePathsWithObstacles(self, obstacleGrid): elif s[0] == '+' and signed:
""" s = s[1:]
:type obstacleGrid: List[List[int]] if len(s) == 0:
:rtype: int return False
"""
m = len(obstacleGrid) for c in s:
n = len(obstacleGrid[0]) if c not in self.digits:
return False
if not m or not n: return True
return 0
if obstacleGrid[0][0] or obstacleGrid[-1][-1]:
return 0 def is_float(self, s):
try:
row_paths = [0 for _ in range(n+1)] dot = s.index('.')
row_paths[1] = 1 before = s[:dot]
after = s[dot+1:]
for row in range(1, m+1):
new_row_paths = [0] if before and before[0] in '+-':
for col in range(1, n+1): before = before[1:]
if obstacleGrid[row-1][col-1]: if before and not self.is_int(before, False):
new_row_paths.append(0) return False
else: if after and not self.is_int(after, False):
new_row_paths.append(new_row_paths[-1] + row_paths[col]) return False
row_paths = new_row_paths return before or after
except:
return row_paths[-1] return False
# python_1_to_1000/067_Add_Binary.py justified.append("".join(line))
class Solution(object):
def addBinary(self, a, b): # python_1_to_1000/069_Sqrt(x).py
"""
:type a: str _author_ = 'jake'
:type b: str _project_ = 'leetcode'
:rtype: str
""" # https://leetcode.com/problems/sqrtx/
result = [] # Implement int sqrt(int x).
carry = 0 # Compute and return the square root of x.
i = len(a)-1
j = len(b)-1 # Newton method. Initial guess of x. Iteratively update guess to be average of previous guess and x // guess.
# Since guess is too high, x // guess is too low.
while carry or i >= 0 or j >= 0: # Terminate when guess^2 <= x.
# Time - O((log x)^3) - log x from nb iterations, log x from multiple and log x from divide
total = carry # Space - O(1)
if i >= 0:
total += int(a[i]) class Solution(object):
i -= 1 def mySqrt(self, x):
if j >= 0: """
total += int(b[j]) :type x: int
j -= 1 :rtype: int
result.append(str(total % 2)) """
carry = total // 2 guess = x
while guess * guess > x:
return "".join(result[::-1]) guess = (guess + x // guess) // 2
return guess
# python_1_to_1000/068_Text_Justification.py - h
class Solution(object):
# python_1_to_1000/071_Simplify_Path.py - m def setZeroes(self, matrix):
"""
_author_ = 'jake' :type matrix: List[List[int]]
_project_ = 'leetcode' :rtype: void Do not return anything, modify matrix in-place instead.
"""
# https://leetcode.com/problems/simplify-path/ if not matrix or not matrix[0]:
# Given an absolute path for a file (Unix-style), simplify it. return 0
# Create result stack. Go up a level if '..'. Stay at same level if '.'. rows = len(matrix)
# Time - O(n) cols = len(matrix[0])
# Space - O(n)
first_row_zero = any([True for c in range(cols) if matrix[0][c] == 0])
class Solution(object): first_col_zero = any([True for r in range(rows) if matrix[r][0] == 0])
def simplifyPath(self, path):
""" for r in range(1, rows):
:type path: str for c in range(1, cols):
:rtype: str if matrix[r][c] == 0:
""" matrix[r][0] = 0
path_list = path.split('/') # does not treat consecutive delimiters as one if delimiter specified matrix[0][c] = 0
result = []
for r in range(1, rows):
for item in path_list: if matrix[r][0] == 0:
if item == '..': # go up one level if possible for c in range(1, cols):
if result: matrix[r][c] = 0
result.pop()
elif item and item != '.': # add item to path for c in range(1, cols):
result.append(item) if matrix[0][c] == 0:
# else ignore '.' and '' for r in range(1, rows):
matrix[r][c] = 0
return '/' + '/'.join(result)
if first_row_zero:
matrix[0] = [0] * cols
# python_1_to_1000/072_Edit_Distance.py - m if first_col_zero:
for r in range(rows):
_author_ = 'jake' matrix[r][0] = 0
_project_ = 'leetcode'
# https://leetcode.com/problems/edit-distance/
# Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. # python_1_to_1000/074_Search_a_2D_Matrix.py - m
# You have the following 3 operations permitted on a word (each 1 step):
# a) Insert a character _author_ = 'jake'
# b) Delete a character _project_ = 'leetcode'
# c) Replace a character
# https://leetcode.com/problems/search-a-2d-matrix/
# Dynamic programming. Base case if either string is empty, return unmatched length of other string. # Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:
# If last characters matched then same cost as matching other characters. Else best case of insert, delete or replace. # Integers in each row are sorted from left to right.
# Time - O(m * n) # The first integer of each row is greater than the last integer of the previous row.
# Space - O(m * n)
# Treat the 2-d matrix as a 1-d list of length rows * cols. Binary search indices from 0 to rows * cols - 1.
class Solution(object): # Time - O(log m + log n)
def minDistance(self, word1, word2): # Space - O(1)
"""
:type word1: str class Solution(object):
:type word2: str def searchMatrix(self, matrix, target):
:rtype: int """
""" :type matrix: List[List[int]]
:type target: int
def edit_distance(i, j): :rtype: bool
if i < 0 or j < 0: """
return i + 1 + j + 1 if not matrix or not matrix[0]:
return False
if (i, j) in memo:
return memo[(i, j)] rows, cols = len(matrix), len(matrix[0])
low, high = 0, rows * cols - 1
if word1[i] == word2[j]:
result = edit_distance(i - 1, j - 1) while high >= low:
else:
result = 1 + min(edit_distance(i - 1, j), mid = (high + low) // 2
edit_distance(i, j - 1), value = matrix[mid // cols][mid % cols] # convert mid to a row and column
edit_distance(i - 1, j - 1))
if target == value:
memo[(i, j)] = result return True
return result if target > value:
low = mid + 1
memo = {} else:
# python_1_to_1000/075_Sort_Colors.py - m # python_1_to_1000/077_Combinations.py - m
# https://leetcode.com/problems/sort-colors/ # https://leetcode.com/problems/combinations/
# Given an array with n objects colored red, white or blue, sort them so that objects of the same color are adjacent, # Given two integers n and k, return all possible combinations of k numbers out of 1 ... n.
# with the colors in the order red, white and blue.
# Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively. # Recursively ignore the last number and choose k form n-1, or use the last number and combine with k-1 from n-1.
# Time - O(k * n! / (k! * (n-k)!)), nCk combinations each of length k
# Overwrite each index with blue. If index was red or white, add a new white and increment white pointer. If index # Space - O(k * n! / (k! * (n-k)!))
# was red, add a new red and increment red pointer.
# Time - O(n) class Solution(object):
# Space - O(1) def combine(self, n, k):
"""
class Solution(object): :type n: int
def sortColors(self, nums): :type k: int
""" :rtype: List[List[int]]
:type nums: List[int] """
:rtype: void Do not return anything, modify nums in-place instead. if k == 0: # or if k == 1 return [[i] for i in range(1,n+1)]
""" return [[]]
next_red, next_white = 0, 0 if n < k: # or if k == n return [[i for i in range(1,n+1)]]
return []
for i in range(len(nums)):
without_last = self.combine(n-1, k)
colour = nums[i]
nums[i] = 2 with_last = [[n] + combo for combo in self.combine(n-1, k-1)]
if colour == 0:
nums[next_red] = 0 # python_1_to_1000/078_Subsets.py - m
next_red += 1
_author_ = 'jake'
_project_ = 'leetcode'
# python_1_to_1000/076_Maximum_Window_Substring.py - h # https://leetcode.com/problems/subsets/
# Given a set of distinct integers, nums, return all possible subsets.
_author_ = 'jake' # The solution set must not contain duplicate subsets.
_project_ = 'leetcode'
# Each bit of binary number form 0 to 2**n - 1 represents whether or not an entry in nums is in that set.
# https://leetcode.com/problems/minimum-window-substring/ # Alternatively, copy partial subsets both with and without each item.
# Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity # Time - O(n * 2**n), 2**n subsets each of length n.
O(n). # Space - O(n * 2**n)
# If there is no such window in S that covers all characters in T, return the empty string "".
# If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S. class Solution(object):
def subsets(self, nums):
# Slide end of window forwards when not all letters in t are matched with window. Slide start of window when all """
# letters are matched. Maintain the required count of each letter (can be negative if excess) and overall to_match. :type nums: List[int]
# Time - O(n) :rtype: List[List[int]]
# Space - O(1) """
nb_subsets = 2**len(nums)
from collections import Counter all_subsets = []
while end < len(s)-1 or to_match == 0: # can extend end or all matched so will increase start
if i >= len(word): # nothing more of word to find if nums[mid] < nums[right]: # RHS is sorted
return True if target > nums[mid] and target <= nums[right]: # check target in range of both ends
if r < 0 or r >= len(board) or c < 0 or c >= len(board[0]): # outside board return self.binary(nums, mid+1, right, target) # target cannot be on LHS
return False return self.binary(nums, left, mid-1, target) # target cannot be on RHS
if word[i] != board[r][c]: # no match letter
return False if nums[left] == nums[mid] and nums[mid] != nums[right]: # LHS is flat and does not include target
return self.binary(nums, mid+1, right, target) # so check RHS
board[r][c] = '*' # set this position so cannot be used again if nums[right] == nums[mid] and nums[mid] != nums[left]: # RHS is flat and does not include target
return self.binary(nums, left, mid-1, target) # so check LHS
if (self.can_find(word, i+1, board, r+1, c) or self.can_find(word, i+1, board, r-1, c) or
self.can_find(word, i+1, board, r, c+1) or self.can_find(word, i+1, board, r, c-1)): if self.binary(nums, left, mid-1, target): # both sides flat, if not fount on one side check the other
return True return True
return self.binary(nums, mid+1, right, target)
board[r][c] = word[i] # if False, reset position to letter
return False
# python_1_to_1000/082_Remove_Duplicates_from_Sorted_List_II.py - m
# python_1_to_1000/080_Remove_Duplicates_from_Sorted_Array_II.py - m
_author_ = 'jake'
_author_ = 'jake' _project_ = 'leetcode'
_project_ = 'leetcode'
# https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii/
# https://leetcode.com/problems/remove-duplicates-from-sorted-array-ii/ # Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the
# Follow up for "Remove Duplicates": original list.
# What if duplicates are allowed at most twice?
# For example, given sorted array nums = [1,1,1,2,2,3], # If node is duplicated, move past all nodes of same value. Else add node to final list.
# Your function should return length = 5, with the first five elements of nums being 1, 1, 2, 2 and 3. # Time - O(n)
# Space - O(1)
# Maintain a pointer to the next index to contain a result. If a new number does not have 2 copies already
# in result then add it. # Definition for singly-linked list.
# Time - O(2) class ListNode(object):
# Space - O(1) def __init__(self, x):
self.val = x
class Solution(object): self.next = None
def removeDuplicates(self, nums):
""" class Solution(object):
:type nums: List[int] def deleteDuplicates(self, head):
:rtype: int """
""" :type head: ListNode
next = 2 # next index to be filled with result :rtype: ListNode
"""
for index in range(2, len(nums)): pseudo = prev = ListNode(None)
pseudo.next = head
if nums[index] != nums[next-2]: # result does not contain 2 copies of this num node = head
nums[next] = nums[index]
next += 1 while node:
return min(next, len(nums)) if node.next and node.val == node.next.val: # node begins a sequence of duplicates
duplicate_value = node.val
node = node.next
# python_1_to_1000/081_Search_in_Rotated_Sorted_Array_II.py - m while node and node.val == duplicate_value: # skip over all duplicates
node = node.next
_author_ = 'jake' prev.next = None # list ends until non-duplicate found
_project_ = 'leetcode'
else: # node is not duplicated
# https://leetcode.com/problems/search-in-rotated-sorted-array-ii/ prev.next = node # add to resulting list
# Follow up for "Search in Rotated Sorted Array": prev = node
# What if duplicates are allowed? node = node.next
# Would this affect the run-time complexity? How and why?
# Write a function to determine if a given target is in the array. return pseudo.next
# When splitting the array at mid, one side contains the rotation point. The other side must be increasing or flat.
# Rotation point side cannot be increasing, only flat or decreasing.
# Therefor if we find an increasing side we know whether to recurse on that side or the other. # python_1_to_1000/083_Remove_Duplicates_from_Sorted_List.py
# Then if either side is not flat we know it is not sorted adn the other side is, so recurse there.
# If both sides are flat we must check them both. _author_ = 'jake'
# Time - O(n) _project_ = 'leetcode'
# Space - O(n)
# https://leetcode.com/problems/remove-duplicates-from-sorted-list/
class Solution(object): # Given a sorted linked list, delete all duplicates such that each element appear only once.
def search(self, nums, target):
""" # If next node is same as node, link node to node.next.next. Else move to next node.
:type nums: List[int] # Time - O(n)
return head
# python_1_to_1000/086_Partition_List.py - m
_author_ = 'jake'
# python_1_to_1000/084_Largest_Rectangle_in_Histogram.py - h _project_ = 'leetcode'
# python_1_to_1000/085_Maximal_Rectangle.py - h
# python_1_to_1000/087_Scramble_String.py - h
_author_ = 'jake'
_project_ = 'leetcode' _author_ = 'jake'
_project_ = 'leetcode'
# https://leetcode.com/problems/maximal-rectangle/
# Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing only 1's and return its area. # https://leetcode.com/problems/scramble-string/
# Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively.
# For each row build a 'histogram' of the number of 1s above and including each column. Then proceed as for problem 084 # To scramble the string, we may choose any non-leaf node and swap its two children.
# and pop a column off the stack whenever its 2 boundaries are lower. # Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1.
# Time - O(m*n)
# Space - O(n) # Base cases of strings containing different characters or same string. Else for all partition points, lest and right
# sides are scrambled versions, before or after swapping.
class Solution(object): # Time - exponential since 4n recursive calls for string of length n.
def maximalRectangle(self, matrix):
""" from collections import Counter
:type matrix: List[List[str]]
:rtype: int class Solution(object):
""" def isScramble(self, s1, s2):
if not matrix or not matrix[0]: """
return 0 :type s1: str
:type s2: str
rows = len(matrix) :rtype: bool
cols = len(matrix[0]) """
count1 = Counter(s1)
max_area = 0 for c in s2:
if c not in count1: return gray
return False
count1[c] -= 1
if count1[c] < 0:
return False
# python_1_to_1000/090_Subsets_II.py - m
if s1 == s2:
return True _author_ = 'jake'
_project_ = 'leetcode'
for partition in range(1, len(s1)):
# https://leetcode.com/problems/subsets-ii/
s1_l = s1[:partition] # partition number of chars from left # Given a collection of integers that might contain duplicates, nums, return all possible subsets.
s1_r = s1[partition:] # last (len(s1) - partition) chars # Note: The solution set must not contain duplicate subsets.
s2_l = s2[:partition]
s2_r = s2[partition:] # Count the frequency of times each num in nums. Starting with the empty subset, for each num append it to all
s2_l_swap = s2[:-partition] # (len(s2) - partition) chars from left # subsets every possible number of times (between 0 and its frequency in nums, inclusive).
s2_r_swap = s2[-partition:] # last partition chars # Time - O(n * 2**n), worst case when nums are all ujnique
# Space - O(n * 2**n)
if (self.isScramble(s1_l, s2_l) and self.isScramble(s1_r, s2_r)) or \
(self.isScramble(s1_l, s2_r_swap) and self.isScramble(s1_r, s2_l_swap)): from collections import Counter
return True
class Solution(object):
return False def subsetsWithDup(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
# python_1_to_1000/088_Merge_Sorted_Array.py """
num_count = Counter(nums)
_author_ = 'jake' results = [[]]
_project_ = 'leetcode'
for num in num_count:
# https://leetcode.com/problems/merge-sorted-array/ results += [partial+[num]*i for i in range(1,num_count[num]+1) for partial in results]
# Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array.
# You may assume that nums1 has enough space (size that is greater or equal to m + n) to hold additional elements from return results
nums2.
# The number of elements initialized in nums1 and nums2 are m and n respectively.
# Start from end of nums1. Move largest elements from each array.
# Time - O(m + n) # python_1_to_1000/091_Decode_Ways.py - m
# Space - O(1)
_author_ = 'jake'
class Solution(object): _project_ = 'leetcode'
def merge(self, nums1, m, nums2, n):
""" # https://leetcode.com/problems/decode-ways/
:type nums1: List[int] # A message containing letters from A-Z is being encoded to numbers using the following mapping:
:type m: int # 'A' -> 1, 'B' -> 2, ..., 'Z' -> 26
:type nums2: List[int] # Given an encoded message containing digits, determine the total number of ways to decode it.
:type n: int
:rtype: void Do not return anything, modify nums1 in-place instead. # Dynamic programming. Calc ways for prefix of length i from prefixes of lengths i-1 and i-2.
""" # Time - O(n)
i, j, k = m - 1, n - 1, m + n - 1 # Space - O(n), could be O(1) by keeping only last 2 values of nb_ways
if i < 0: # Nothing to move if only nums1 remain, else move rest of nums2 nb_ways = [0] * (len(s)+1) # nb_ways[i] is number of ways to decode prefix of length i
nums1[:k+1] = nums2[:j+1] nb_ways[0] = 1 # required else '10' will be 0
if s[0] != '0':
nb_ways[1] = 1
# python_1_to_1000/089_Gray_Code.py - m
for i in range(1, len(s)):
_author_ = 'jake'
_project_ = 'leetcode' if s[i] != '0': # last char is not '0'
nb_ways[i+1] += nb_ways[i] # use all ways to decode without this char
# https://leetcode.com/problems/gray-code/ if 10 <= int(s[i-1:i+1]) <= 26: # last 2 form int between 10 and 26
# The gray code is a binary numeral system where two successive values differ in only one bit. nb_ways[i+1] += nb_ways[i-1] # use all ways to decode without last 2 chars
# Given a non-negative integer n representing the total number of bits in the code, print the sequence of gray code.
# A gray code sequence must begin with 0. For example, given n = 2, return [0,1,3,2]. Its gray code sequence is: return nb_ways[-1]
# 00 - 0, 01 - 1, 11 - 3, 10 - 2
# Grey sequence of n + 1 is formed starting with sequence for n, then appending the reverse of that sequence with
# the extra bit set. # python_1_to_1000/092_Reverse_Linked_List_II.py - m
# GC(0) = [0], GC(1) = [0,1], GC(2) = [0,1,3,2], GC(3) = [0,1,3,2,6,7,5,4]
# Time - O(2**n) _author_ = 'jake'
# Space - O(2**n) _project_ = 'leetcode'
self.val = x # Given a binary tree, return the inorder traversal of its nodes' values.
self.next = None # Note: Recursive solution is trivial, could you do it iteratively?
class Solution(object): # From root, go as far left as possible pushing all nodes onto stack. While nodes on stack, pop a node and add it to
def reverseBetween(self, head, m, n): # the result. Its left child (if any) has already been visited because it was added to the stack later so popped
""" # earlier. If the node has a right child, add that child and all its left branch to the stack.
:type head: ListNode # Time - O(n)
:type m: int # Space - O(n)
:type n: int
:rtype: ListNode # Definition for a binary tree node.
""" # class TreeNode(object):
pseudo = ListNode(None) # create a new pseudo head # def __init__(self, x):
pseudo.next = head # self.val = x
node = pseudo # self.left = None
n -= m # n = nb nodes to be reversed - 1 # self.right = None
while m > 1: # find the tail of the first non-reversed section class Solution(object):
node = node.next def inorderTraversal(self, root):
m -= 1 """
:type root: TreeNode
reversed_head = None :rtype: List[int]
next_reverse = node.next """
stack, result = [], []
while n >= 0: # add next_reverse in front of reversed_head
tail = next_reverse.next while root: # make top of stack the smallest value
next_reverse.next = reversed_head stack.append(root)
reversed_head = next_reverse root = root.left
next_reverse = tail
n -= 1 while stack:
node.next.next = tail # link tail of reversed section to second non-reversed section node = stack.pop()
node.next = reversed_head # link tail of the first non-reversed section to reversed section result.append(node.val)
# https://leetcode.com/problems/restore-ip-addresses/
# Given a string containing only digits, restore it by returning all possible valid IP address combinations. # python_1_to_1000/095_Unique_Binary_Search_Trees_II.py - m
# E.g. given "25525511135", return ["255.255.11.135", "255.255.111.35"]. (Order does not matter)
_author_ = 'jake'
# For each of the 4 sections of an IP address, use 3 chars if between 100 and 255, 2 if > 10 and always use 1 char - _project_ = 'leetcode'
# provided that the remaining chars are not too few or too many to make an IP address.
# an IP address # https://leetcode.com/problems/unique-binary-search-trees-ii/
# Time - O(1), max of 4**3 possibilities for any s # Given an integer n, generate all structurally unique BST's (binary search trees) that store values 1...n.
# Space - O(1)
# Any number i from 1 to n is the root. Numbers less than i form the left subtree, numbers greater from the right.
class Solution(object): # Time - O(n**2 * Catalan(n)) where Catalan(n) = 2n! / (n+1)!n!
def restoreIpAddresses(self, s): # Space - O(n * Catalan(n))
"""
:type s: str # Definition for a binary tree node.
:rtype: List[str] class TreeNode(object):
""" def __init__(self, x):
NB_SECTIONS = 4 self.val = x
if 3 * NB_SECTIONS < len(s) < NB_SECTIONS: # cannot make any IPs self.left = None
return [] self.right = None
# https://leetcode.com/problems/binary-tree-inorder-traversal/ # python_1_to_1000/096_Unique_Binary_Search_Trees.py - m
_author_ = 'jake' # https://leetcode.com/problems/validate-binary-search-tree/
_project_ = 'leetcode' # Given a binary tree, determine if it is a valid binary search tree (BST).
# Assume a BST is defined as follows:
# https://leetcode.com/problems/unique-binary-search-trees/ # The left subtree of a node contains only nodes with keys less than the node's key.
# Given an integer n, count all structurally unique BST's (binary search trees) that store values 1...n. # The right subtree of a node contains only nodes with keys greater than the node's key.
# Both the left and right subtrees must also be binary search trees.
# Dynamic programming. Base case of 1 for n = 0 or 1. For each of n possible root nodes, multiply the
# possible left subtrees with the right subtrees. # Perform an inorder traversal and check that each node is greater than the previous. Does not work if equal nodes
# Time - O(n**2) # are allowed.
# Space - O(n) # Alternatively track the upper and lower bounds possible for each node, depending on parents.
# Time - O(n)
# Definition for a binary tree node. # Space - O(n), or log n if balanced
class TreeNode(object):
def __init__(self, x): # Definition for a binary tree node.
self.val = x class TreeNode(object):
self.left = None def __init__(self, x):
self.right = None self.val = x
self.left = None
class Solution(object): self.right = None
def numTrees(self, n):
""" class Solution(object):
:type n: int def isValidBST(self, root):
:rtype: int """
""" :type root: TreeNode
memo = [-1] * (n+1) # memo[i] is number of ways for i nodes :rtype: bool
return self.helper(n, memo) """
self.correct = True
def helper(self, n, memo): self.prev = float('-inf')
if n <= 1: self.inorder(root)
return 1 # 1 tree for n==0 (empty tree) and 1 tree for n==1 return self.correct
self.inorder(node.right)
# python_1_to_1000/097_Interleaving_String.py - m
class Solution2(object):
_author_ = 'jake' def isValidBST(self, root):
_project_ = 'leetcode' return self.valid(root, float('-inf'), float('inf'))
# https://leetcode.com/problems/interleaving-string/ def valid(self, node, lower, upper): # node.val must be above lower and below upper
# Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. if not node:
return True
# If the next char of s1 or s2 matches s3, recurse on the remainder. if node.val <= lower or node.val >= upper: # can be amended if equal values are allowed
# Time - O(m * n), every prefix of s1 * every prefix of s2 return False
# Space - O(m * n) return self.valid(node.left, lower, node.val) and self.valid(node.right, node.val, upper)
class Solution(object):
def isInterleave(self, s1, s2, s3):
""" # python_1_to_1000/099_Recover_Binary_Search_Tree.py - m
:type s1: str
:type s2: str _author_ = 'jake'
:type s3: str _project_ = 'leetcode'
:rtype: bool
""" # https://leetcode.com/problems/recover-binary-search-tree/
if len(s1) + len(s2) != len(s3): # early return # The values of 2 nodes of a binary search tree (BST) are swapped by mistake.
return False # Recover the tree without changing its structure.
return self.helper(s1, s2, s3, 0, 0, {})
# Perform an inorder traversal tracking the previous node. The first time a non-increasing node value is found,
# store the previous node. The second time a non-increasing node value is found, store the node.
def helper(self, s1, s2, s3, i, j, memo): # i, j are indices of next char to be matched in s1, s2 # E.g. for 1,2,3,8,5,6,7,4,9 we store 8 and 4.
# Time - O(n)
if i >= len(s1) or j >= len(s2): # base case, one string already matched # Space - O(n), recursion depth worst case, log n if balanced
return s1[i:] + s2[j:] == s3[i+j:]
# Definition for a binary tree node.
if (i, j) in memo: class TreeNode(object):
return memo[(i, j)] def __init__(self, x):
self.val = x
result = False self.left = None
if s1[i] == s3[i+j] and self.helper(s1, s2, s3, i+1, j, memo): self.right = None
result = True
elif s2[j] == s3[i+j] and self.helper(s1, s2, s3, i, j+1, memo): class Solution(object):
result = True def recoverTree(self, root):
"""
memo[(i, j)] = result :type root: TreeNode
return result :rtype: void Do not return anything, modify root in-place instead.
"""
self.swapped1 = None
self.swapped2 = None
# python_1_to_1000/098_Validate_Binary_Search_Tree.py - m self.prev = TreeNode(float('-inf'))
self.inorder(root)
_author_ = 'jake' self.swapped1.val, self.swapped2.val = self.swapped2.val, self.swapped1.val
_project_ = 'leetcode'
# python_1_to_1000/100_Same_Tree.py # Create a list of all non-null nodes from the nodes in the level above.
# Time - O(n)
_author_ = 'jake' # Space - O(n)
_project_ = 'leetcode'
# Definition for a binary tree node.
# https://leetcode.com/problems/same-tree/ # class TreeNode(object):
# Given two binary trees, write a function to check if they are equal or not. # def __init__(self, x):
# Two binary trees are considered equal if they are structurally identical and the nodes have the same value. # self.val = x
# self.left = None
# Traverse both trees, checking nodes exist in same places and values are same. Could preorder, inorder or postorder. # self.right = None
# Time - O(min(m, n))
# Space - O(min(m, n)), or log is balanced class Solution(object):
def levelOrder(self, root):
# Definition for a binary tree node. """
class TreeNode(object): :type root: TreeNode
def __init__(self, x): :rtype: List[List[int]]
self.val = x """
self.left = None result = []
self.right = None if not root:
return result
class Solution(object):
def isSameTree(self, p, q): level_nodes = [root]
"""
:type p: TreeNode while level_nodes:
:type q: TreeNode
:rtype: bool new_level_nodes = []
""" result.append([])
if not p and not q:
return True for node in level_nodes:
if not p or not q: result[-1].append(node.val)
return False if node.left:
new_level_nodes.append(node.left)
if p.val != q.val: if node.right:
return False new_level_nodes.append(node.right)
return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)
level_nodes = new_level_nodes
return result
# python_1_to_1000/101_Symmetric_Tree.py
# python_1_to_1000/103_Binary_Tree_Zigzag_Level_Order_Traversal.py - m
_author_ = 'jake'
_project_ = 'leetcode' _author_ = 'jake'
_project_ = 'leetcode'
# https://leetcode.com/problems/symmetric-tree/
# Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). # https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/
# Given a binary tree, return the zigzag level order traversal of its nodes' values.
# Check if left and right subtrees are both present or not, then if root values are equal. Then recurse on their # (ie, from left to right, then right to left for the next level and alternate between).
# subtrees being mirrors - left/left of right/right and left/right of right/left
# Time - O(n) # Alternately append new nodes from left to right and right to left.
# Space - O(n) # Time - O(n)
# Space - O(n)
# Definition for a binary tree node.
# class TreeNode(object): # Definition for a binary tree node.
# def __init__(self, x): # class TreeNode(object):
# self.val = x # def __init__(self, x):
# self.left = None # self.val = x
# self.right = None # self.left = None
# self.right = None
class Solution(object):
def isSymmetric(self, root): class Solution(object):
""" def zigzagLevelOrder(self, root):
:type root: TreeNode """
:rtype: bool :type root: TreeNode
""" :rtype: List[List[int]]
if not root: """
return True if not root:
return self.is_mirror(root.left, root.right) return []
traversal = []
def is_mirror(self, left_node, right_node):
level = [root]
if not left_node and not right_node: forward = True
return True
while level:
return root
new_level = []
if forward: preorder.reverse() # reverse so we can pop in O(1) time
traversal.append([n.val for n in level]) inorder.reverse()
else: return build(None)
traversal.append([n.val for n in level[::-1]])
return traversal # Construct in postorder. Last element of postorder is root. Partition preorder about this element.
# Build the right subtree first until postorder[0] is not in inorder.
# Time - O(n)
# Space - O(n)
# python_1_to_1000/105_Construct_Binary_Tree_from_Preorder_and_Inorder_Traversal.py - m # https://leetcode.com/problems/binary-tree-level-order-traversal-ii/
# Given a binary tree, return the bottom-up level order traversal of its nodes' values.
_author_ = 'jake' # I.e. from left to right, level by level from leaf to root.
_project_ = 'leetcode'
# Perform an inorder traversal, tracking depth and appending node values to corresponding sub-list. Reverse
# https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/ # result before returning.
# Given preorder and inorder traversal of a tree, construct the binary tree. # Time - O(n)
# You may assume that duplicates do not exist in the tree. # Space - O(n)
# Build until we reach stop value, initially None. Take first preorder as root then recurse left until inorder is # Definition for a binary tree node.
# root value. Then discard inorder and recurse right until final stop. class TreeNode(object):
# Time - O(n) def __init__(self, x):
# Space - O(n) self.val = x
self.left = None
from collections import deque self.right = None
root.left = left_subtree
node_as_list[0] = node_as_list[0].next # update entry to next node of linked-list
# https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/
# Given an array where elements are sorted in ascending order, convert it to a height balanced BST.
# python_1_to_1000/110_Balanced_Binary_Tree.py
# Mid element is root, recursively form left and right subtrees.
# Time - O(n) _author_ = 'jake'
# Space - O(n) _project_ = 'leetcode'
# Count the length of the list. Form left subtree from nodes before mid. Mid node forms root, then right subtree
# from nodes after mid. When a new tree node is made, advance the linked list pointer. Bottom-up approach.
# Time - O(n)
# Space - O(n) # python_1_to_1000/111_Minimum_Depth_of_Binary_Tree.py
def list_to_bst(self, node_as_list, start, end): # convert linked-list nodes from start to end (inclusive) l = self.minDepth(root.left)
r = self.minDepth(root.right)
if start > end:
return None if not l or not r:
return 1 + l + r
mid = (start + end) // 2
return 1 + min(l, r)
left_subtree = self.list_to_bst(node_as_list, start, mid - 1) # will update contents of node_as_list to
# become the mid node of linked list
root = TreeNode(node_as_list[0].val)
# python_1_to_1000/112_Path_Sum.py # Each node only has a right child. Left subtree is flattened before right.
_author_ = 'jake' # Records the root of the previous subtree flattened as an instance field.
_project_ = 'leetcode' # Flattens right subtree, after which self.prev is the root of the right subtree.
# Then connects the flattened left subtree to the flattened right subtree.
# https://leetcode.com/problems/path-sum/ # Then removes the link from the root to the old left subtree, and sets the
# Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up # root.right to the root of the left subtree (now flattened).
# all the values along the path equals the given sum. # Time - O(n)
# Space - O(n)
# Base cases of False if no node and True if leaf node with correct sum. Else subtract node value and check if
# True in either subtree. # Definition for a binary tree node.
# Time - O(n) class TreeNode(object):
# Space - O(n) def __init__(self, x):
self.val = x
# Definition for a binary tree node. self.left = None
class TreeNode(object): self.right = None
def __init__(self, x):
self.val = x class Solution(object):
self.left = None
self.right = None def __init__(self): # instance field self.prev to track previous node
self.prev = None
class Solution(object):
def hasPathSum(self, root, sum): def flatten(self, root):
""" """
:type root: TreeNode :type root: TreeNode
:type sum: int :rtype: None Do not return anything, modify root in-place instead.
:rtype: bool """
""" if not root:
if not root: return
return False
self.flatten(root.right)
sum -= root.val self.flatten(root.left)
if sum == 0 and not root.left and not root.right: # leaf node
return True root.left = None
root.right = self.prev
return self.hasPathSum(root.left, sum) or self.hasPathSum(root.right, sum) self.prev = root
# python_1_to_1000/113_Path_Sum_II.py - m # python_1_to_1000/115_Distinct_Subsequences.py - h
# https://leetcode.com/problems/path-sum-ii/ # https://leetcode.com/problems/distinct-subsequences/
# Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum. # Given a string S and a string T, count the number of distinct subsequences of T in S.
# A subsequence of a string is a new string which is formed from the original string by deleting some (can be none)
# Maintain a partial path, appending latest node and decrementing target. When path has been explored, pop node off # of the characters without disturbing the relative positions of the remaining characters.
# partial path. Base cases are no node and leaf with remaining target of zero.
# Time - O(n log n), balanced tree has n/2 leaves and height log n # Dynamic programming. For all prefixes of S and T calculate the number of sequences. Base case is that the prefix
# Space - O(n log n), every path of balanced tree has correct sum # of T is the empty string, which is one subsequence of every prefix of S.
# The number of times T[:r] is a subsequence of S[:c] is the number of times T[:r] is a subsequence of S[:c - 1], plus
# Definition for a binary tree node. # if the last chars of T[:r] and S[:c] match then every T[:r - 1] subsequence of S[:c] can also be extended.
class TreeNode(object): # empty string is a subsequence of any string.
def __init__(self, x): # Time - O(m * n) where m = len(S) and n = len(T)
self.val = x # Space - O(m)
self.left = None
self.right = None
class Solution(object):
class Solution(object): def numDistinct(self, s, t):
def pathSum(self, root, sum): """
""" :type s: str
:type root: TreeNode :type t: str
:type sum: int :rtype: int
:rtype: List[List[int]] """
""" prev_subsequences = [1 for _ in range(len(s) + 1)] # empty string is always one subsequence of any string
paths = []
self.preorder(root, sum, [], paths) for r in range(1, len(t) + 1): # first r characters of T, i.e. T[:r]
return paths
subsequences = [0 for _ in range(len(s) + 1)]
def preorder(self, node, target, partial, paths):
for c in range(r, len(s) + 1): # first c chars of S. If c < r then no possibilities
if not node:
return subsequences[c] = subsequences[c - 1] # all T[:r] subsequences of S[:c - 1] are also
# subsequences of S[:c]
target -= node.val if s[c - 1] == t[r - 1]: # last chars match, add T[:r-1] subsequences of S[:c-1]
partial.append(node.val) subsequences[c] += prev_subsequences[c - 1]
if target == 0 and not node.left and not node.right:
paths.append(partial[:]) prev_subsequences = subsequences
partial.pop()
# python_1_to_1000/116_Populating_Next_Right_Pointers_in_Each_Node.py - m
# python_1_to_1000/114_Flatten_Binary_Tree_to_Linked_List.py - m
_author_ = 'jake'
_author_ = 'jake' _project_ = 'leetcode'
_project_ = 'leetcode'
# https://leetcode.com/problems/populating-next-right-pointers-in-each-node/
# https://leetcode.com/problems/flatten-binary-tree-to-linked-list/ # Given a binary tree, populate each next pointer to point to its next right node.
# Given a binary tree, flatten it to a linked list in-place. # If there is no next right node, the next pointer should be set to NULL.
# You may only use constant extra space. # Given numRows, generate the first numRows of Pascal's triangle.
# You may assume that it is a perfect binary tree (ie, all leaves are at the same level, and every parent has two
children). # Next row is sum of consecutive pairs of items from previous row.
# Time - O(n**2)
# Breadth first search by level. # Space - O(n**2)
# Time - O(n)
# Space - O(n) class Solution(object):
def generate(self, numRows):
# Definition for binary tree with next pointer. """
class TreeLinkNode(object): :type numRows: int
def __init__(self, x): :rtype: List[List[int]]
self.val = x """
self.left = None if numRows == 0:
self.right = None return []
self.next = None
pascal = [[1]]
class Solution(object):
def connect(self, root): for i in range(1, numRows):
"""
:type root: TreeLinkNode pascal.append([1])
:rtype: nothing for num1, num2 in zip(pascal[-2][:-1], pascal[-2][1:]):
""" pascal[-1].append(num1 + num2)
level = [root] pascal[-1].append(1)
while level and level[0]: # if first item is None then all are None because perfect, so terminate return pascal
next_level = []
prev = None
# python_1_to_1000/119_Pascal's_Triangle_II.py
for node in level: # set next right pointer
if prev: _author_ = 'jake'
prev.next = node _project_ = 'leetcode'
prev = node
# https://leetcode.com/problems/pascals-triangle-ii/
next_level.append(node.left) # add nodes to next level list, do not check if None # Given an index k, return the kth row of the Pascal's triangle.
next_level.append(node.right)
# Next row is sum of consecutive pairs of previous row.
level = next_level # Time - O(n**2)
# Space - O(n)
class Solution(object): # Bottom-ip dynamic programming. Min path is value of that element + min of the 2 paths to elements below.
def connect(self, root): # Time - O(n**2) for triangle height n since all elements visited
""" # Space - O(1), modifies input data
:type root: TreeLinkNode
:rtype: nothing class Solution(object):
""" def minimumTotal(self, triangle):
if not root: """
return :type triangle: List[List[int]]
level = [root] :rtype: int
"""
while level: for row in range(len(triangle)-2, -1, -1):
next_level = []
prev = None for col in range(len(triangle[row])):
for node in level: triangle[row][col] += min(triangle[row+1][col], triangle[row+1][col+1])
if prev:
prev.next = node return triangle[0][0]
prev = node
if node.left:
next_level.append(node.left) # python_1_to_1000/121_Best_Time_to_Buy_and_Sell_Stock.py
if node.right:
next_level.append(node.right) _author_ = 'jake'
_project_ = 'leetcode'
level = next_level
# https://leetcode.com/problems/best-time-to-buy-and-sell-stock/
# Say you have an array for which the ith element is the price of a given stock on day i.
# If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock),
# python_1_to_1000/118_Pascal's_Triangle.py # design an algorithm to find the maximum profit.
_author_ = 'jake' # Record the max cash after buying stock at any point previously (which is negative), and the max cash after selling
_project_ = 'leetcode' # as the cash after boying + sale proceeds.
# Time - O(n)
# https://leetcode.com/problems/pascals-triangle/ # Space - O(1)
# def __init__(self, x):
class Solution(object): # self.val = x
def maxProfit(self, prices): # self.left = None
""" # self.right = None
:type prices: List[int]
:rtype: int class Solution(object):
""" def maxPathSum(self, root):
buy = float('-inf') # maximum cash balance after buying a stock """
sell = 0 # maximum cash balance after buying and selling a stock :type root: TreeNode
:rtype: int
for price in prices: """
buy = max(-price, buy) # max of buying earlier or now return self.helper(root)[0]
sell = max(price + buy, sell) # max of selling earlier or now
def helper(self, node): # returns tuple of (via, down) where via is max path sum via (and including) this node
return sell # or via any node below, down is max path sum downwards from this node
if not node:
return float('-inf'), 0 # -inf for via if no node since path must have at least one node
"""
:type beginWord: str new_front = set()
:type endWord: str for word in front:
:type wordList: List[str]
:rtype: List[List[str]] visited.add(word) # add word to set of those already removed from frontiers
"""
if endWord not in wordList: for i in range(len(word)): # add reachable words to frontier
return [] next_words = graph[word[:i] + '_' + word[i + 1:]]
next_words -= visited # apart from if already removed from a frontier
wordList = set(wordList) # convert to set for O(1) lookup new_front |= next_words
left, right = {beginWord}, {endWord} # frontiers at both ends
left_parents, right_parents = defaultdict(set), defaultdict(set) # map word to its parent length += 1
swapped = False # have the frontiers been swapped? front = new_front
while left and right and not (left & right): # while both frontiers and no intersection if len(back) < len(front): # expand the smaller frontier next
front, back = back, front
if len(right) < len(left): # swap to expand smaller frontier
left, right = right, left return 0
left_parents, right_parents = right_parents, left_parents
swapped = not swapped
next_left = defaultdict(set)
for word in left: # python_1_to_1000/128_Longest_Consecutive_Sequence.py - m
for char in string.ascii_lowercase:
for i in range(len(beginWord)): _author_ = 'jake'
n = word[:i] + char + word[i + 1:] # replace every position with every char _project_ = 'leetcode'
if n in wordList and n not in left_parents: # valid word not been used
next_left[n].add(word) # https://leetcode.com/problems/longest-consecutive-sequence/
# Given an unsorted array of integers, find the length of the longest consecutive elements sequence.
left_parents.update(next_left)
left = set(next_left.keys()) # Test if each number starts a new sequence, if it does then count that sequence.
# Time - O(n), visits each number at most twice
if swapped: # swap back # Space - O(n)
left, right = right, left
left_parents, right_parents = right_parents, left_parents class Solution(object):
def longestConsecutive(self, nums):
ladders = [[word] for word in left & right] # start from central intersection """
while ladders and ladders[0][0] not in beginWord: # extend ladders left to start :type nums: List[int]
ladders = [[p] + l for l in ladders for p in left_parents[l[0]]] :rtype: int
while ladders and ladders[0][-1] != endWord: # extend ladders right to end """
ladders = [l + [p] for l in ladders for p in right_parents[l[-1]]] numset = set(nums) # no ordering, O(1) lookup
longest = 0
return ladders
for num in numset:
if front & back: # intersection between frontiers if not node: # no path to leaves
return length return 0
partial = 10 * partial + node.val # incorporate this node.val _author_ = 'jake'
_project_ = 'leetcode'
if not node.left and not node.right: # base case, leaf
return partial # https://leetcode.com/problems/palindrome-partitioning-ii/
# Given a string s, partition s such that every substring of the partition is a palindrome.
return self.helper(node.left, partial) + self.helper(node.right, partial) # Return the minimum cuts needed for a palindrome partitioning of s.
# Initialise worst case for each prefix as length of prefix - 1. For each character expand outwards both odd and even
# python_1_to_1000/130_Surrounded_Regions.py - m # length palindromes. Whenever a palindrome is found, update min_cuts for that palindrome plus the left prefix.
# Time - O(n**2)
_author_ = 'jake' # Space - O(n)
_project_ = 'leetcode'
class Solution(object):
# https://leetcode.com/problems/surrounded-regions/ def minCut(self, s):
# Given a 2D board containing 'X' and 'O' (the letter O), capture all regions surrounded by 'X'. """
# A region is captured by flipping all 'O's into 'X's in that surrounded region. :type s: str
:rtype: int
# All edge cells containing 'O' and their adjoining 'O' cannot be surrounded. Temporarily flag these cells, by depth- """
# first search. Then convert all unflagged 'O' (that can be surrounded) to 'X'. min_cuts = [i-1 for i in range(len(s)+1)] # min_cuts[i] is min cuts for prefix s[:i] of length i
# Time - O(m * n)
# Space - O(m * n) for i in range(len(s)): # for each character as centre of palindrome
while to_expand: # if cell contains 'O', change to temporary 'T' and add neighbours to stack _author_ = 'jake'
row, col = to_expand.pop() _project_ = 'leetcode'
if 0 <= row < rows and 0 <= col < cols and board[row][col] == 'O':
board[row][col] = 'T' # https://leetcode.com/problems/clone-graph/
for dr, dc in [(1, 0), (0, 1), (-1, 0), (0, -1)]: # Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors
to_expand.append((row + dr, col + dc))
# When a new node is discovered it is copied, added to mapping and to_clone. Main while loop makes directed edges
for row in range(rows): # change all 'T' back to 'O' and all 'O' to 'X' # to neighbors.
for col in range(cols): # Time - O(m + n), edges + nodes
if board[row][col] == 'O': # Space - O(m + n)
board[row][col] = 'X'
elif board[row][col] == 'T': # Definition for a undirected graph node
board[row][col] = 'O' class UndirectedGraphNode(object):
def __init__(self, x):
self.label = x
# python_1_to_1000/131_Palindrome_Partitioning.py - m self.neighbors = []
# python_1_to_1000/134_Gas_Station.py - m
_author_ = 'jake'
# python_1_to_1000/132_Palindrome_Partitioning_II.py - h _project_ = 'leetcode'
return xor
# https://leetcode.com/problems/gas-station/
# There are N gas stations along a circular route, where the amount of gas at station i is gas[i].
# You have a car with an unlimited gas tank and it costs cost[i] of gas to travel from station i to its next # python_1_to_1000/137_Single_Number_II.py - m
# station (i+1). You begin the journey with an empty tank at one of the gas stations.
# Return the starting gas station's index if you can travel around the circuit once, otherwise return -1. _author_ = 'jake'
_project_ = 'leetcode'
# If total gas >= total cost then a circuit is possible.
# Iterate round the circuit, updating current tank balance and total. If current tank is negative, cannot start at # https://leetcode.com/problems/single-number-ii/
# that station so update start to next possible station. # Given an array of integers, every element appears three times except for one. Find that single one.
# Time - O(n)
# Space - O(1) # If a bit is set in num, but not set in ones or twos then that bit is then set in ones.
# If a bit is set in num, set in ones but not in twos then that bit is then set in twos and not ones.
class Solution(object): # If a bit is set in num, but not set in ones or twos then that bit is then set in ones.
def canCompleteCircuit(self, gas, cost): # Time - O(n)
""" # Space - O(1)
:type gas: List[int]
:type cost: List[int] class Solution(object):
:rtype: int def singleNumber(self, nums):
""" """
start, tank, total = 0, 0, 0 :type nums: List[int]
:rtype: int
for station in range(len(gas)): """
balance = gas[station] - cost[station] ones, twos = 0, 0
tank += balance
total += balance for num in nums:
if tank < 0: ones = (ones ^ num) & ~twos # xor of all nums that have appeared once only
start = station + 1 twos = (twos ^ num) & ~ones # xor of all nums that have appeared twice only
tank = 0
return ones
return -1 if total < 0 else start
# python_1_to_1000/135_Candy.py - h # python_1_to_1000/138_Copy_List_with_Random_Pointer.py
# https://leetcode.com/problems/candy/ # https://leetcode.com/problems/copy-list-with-random-pointer/
# There are N children standing in a line. Each child is assigned a rating value. # A linked list is given such that each node contains an additional random pointer which could point to any node in the
# You are giving candies to these children subjected to the following requirements: list or null.
# Each child must have at least one candy. # Return a deep copy of the list.
# Children with a higher rating get more candies than their neighbors.
# What is the minimum candies you must give? # Duplicate every node and insert copy in list after original node. Link copied nodes to random pointers, which
# follow random pointers of original nodes. Separate out original and copied lists.
# Find how many candies are required due to children on left and then on right. # Time - O(n)
# Result for each child is the higher of those values. # Space - O(1)
# Time - O(n)
# Space - O(n) # Definition for singly-linked list with a random pointer.
class RandomListNode(object):
class Solution(object): def __init__(self, x):
def candy(self, ratings): self.label = x
""" self.next = None
:type ratings: List[int] self.random = None
:rtype: int
""" class Solution(object):
left = [1 for _ in range(len(ratings))] # default to 1 per child def copyRandomList(self, head):
right = [1 for _ in range(len(ratings))] """
:type head: RandomListNode
for i in range(1, len(ratings)): # increase above previous child if greater rating :rtype: RandomListNode
if ratings[i] > ratings[i-1]: """
left[i] = left[i-1] + 1 node = head
while node:
candies = left[-1] # rightmost child not included in loop below next = node.next
for i in range(len(ratings)-2, -1, -1): copy = RandomListNode(node.label)
if ratings[i] > ratings[i+1]: # increase if greater rating node.next = copy
right[i] = right[i+1] + 1 copy.next = next
candies += max(left[i], right[i]) # child gets higher of candies due to left and right node = next
# Dynamic programming. A prefix can be made from words in dictionary if it can be split into a shorter prefix # Increment fast pointer by 2 nodes and slow pointer by 1 node per time step. If loop, fast will catch up with slow
# that can be made and another word in dictionary. # else fast will reach end.
# Time - O(n**3), there are O(n**2) substrings s[j:i], each taking O(n) to create # Time - O(n)
# Space - O(n) # Space - O(1)
# python_1_to_1000/140_Word_Break_II.py - h
# Test if word can be broken as per problem 139. For all prefixes of s in the dictionary, recurse on the suffix. # If there are k nodes before a cycle of c nodes, when slow reaches start of loop, fast is k % c into loop.
# Time - O(n**3 * 2**(n-1)) # When fast reaches slow, both are c - k % c into the loop. Restart fast at head and move both 1 step at a time.
# Space - O(n * 2**(n-1)), 2**(n-1) possible partitions of string of length n (every combination of gaps between words) # After k steps, both are at start of loop.
# each partiton is of length n. Memo for shorter suffixes does not impact big O. # Time - O(n)
# Space - O(1)
class Solution(object):
# Definition for singly-linked list.
def canBreak(self, s, wordDict): class ListNode(object):
can_make = [False] * (len(s)+1) # can_make[i] is True if can make prefix of length i def __init__(self, x):
can_make[0] = True self.val = x
for i in range(1, len(s)+1): # prefix length self.next = None
for j in range(i-1, -1, -1): # j is existing prefix, start with longest + shortest new word
if can_make[j] and s[j:i] in wordDict: class Solution(object):
can_make[i] = True def detectCycle(self, head):
break """
return can_make[-1] :type head: ListNode
:rtype: ListNode
"""
def wordBreak(self, s, wordDict): fast, slow = head, head
""" while fast and fast.next:
:type s: str fast = fast.next.next
:type wordDict: Set[str] slow = slow.next
:rtype: List[str] if fast == slow:
"""
if not self.canBreak(s, wordDict): fast = head
return [] while fast != slow:
result_lists = self.break_word(s, 0, wordDict, {}) fast = fast.next
return [" ".join(result) for result in result_lists] # convert back to strings slow = slow.next
return slow
def break_word(self, s, left, wordDict, memo): # break from s[left] onwards return None
# set slow to mid for odd length lists, first of second half for even # Definition for a binary tree node.
fast, slow = head, head class TreeNode(object):
while fast and fast.next: def __init__(self, x):
fast = fast.next.next self.val = x
slow = slow.next self.left = None
self.right = None
# reverse nodes after slow (slow has pointers from both sides)
prev, node = None, slow from collections import deque
while node:
prev, node.next, node = node, prev, node.next class Solution(object):
def postorderTraversal(self, root):
first, second = head, prev # heads of the normal and reversed lists """
while second.next: :type root: TreeNode
first.next, first = second, first.next # insert second after first :rtype: List[int]
second.next, second = first, second.next # insert first after second """
if not root:
return []
preorder = [] # python_1_to_1000/146_LRU_Cache.py - m
stack = [root]
_author_ = 'jake'
while stack: _project_ = 'leetcode'
node = stack.pop()
preorder.append(node.val) # https://leetcode.com/problems/lru-cache/
if node.right: # Design and implement a data structure for Least Recently Used cache. It should support the following operations:
stack.append(node.right) # push right first so left is popped first # get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
if node.left: # set(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity,
stack.append(node.left) # it should invalidate the least recently used item before inserting a new item.
return preorder # Dictionary stores keys with values of nodes. Nodes form double linked list containing key, value pairs. DLL is in
# order of use with least recent at head and most recent at tail.
# Time - O(1) to set and get
class Solution2(object): # Space - O(n)
def preorderTraversal(self, root):
result = [] class Node:
self.preorder(root, result) def __init__(self, key, val):
return result self.key = key
self.val = val
def preorder(self, node, result): self.prev = None
if not node: self.next = None
return
result.append(node.val) class DLL:
self.preorder(node.left, result) def __init__(self):
self.preorder(node.right, result) self.head = Node(None, None) # least recently used, remove at head
self.tail = Node(None, None) # most recently used, add and update at tail
self.head.next = self.tail
self.tail.prev = self.head
# python_1_to_1000/145_Binary_Tree_Postorder_Traversal.py
def insert(self, node):
_author_ = 'jake' node.prev, self.tail.prev.next = self.tail.prev, node
_project_ = 'leetcode' node.next, self.tail.prev = self.tail, node
class LRUCache(object):
# Base case is empty list or single node. Else recursively split list in half, sort halves and merge.
def get(self, key): # Time - O(n log n)
""" # Space - O(n)
:rtype: int
""" # Definition for singly-linked list.
if key not in self.mapping: class ListNode(object):
return -1 def __init__(self, x):
node = self.mapping[key] self.val = x
self.queue.update(node) self.next = None
return node.val
class Solution(object):
def sortList(self, head):
def set(self, key, value): """
""" :type head: ListNode
:type key: int :rtype: ListNode
:type value: int """
:rtype: nothing if not head or not head.next:
""" return head
if key in self.mapping: # update value and move node to tail
node = self.mapping[key] fast, slow, prev = head, head, None
node.val = value while fast and fast.next:
self.queue.update(node) prev, slow, fast = slow, slow.next, fast.next.next
return
prev.next = None
node = Node(key, value) # else new key one = self.sortList(head)
self.mapping[key] = node two = self.sortList(slow)
self.queue.insert(node)
return self.merge(one, two)
if self.capacity == 0: # cache is full, eject oldest
removed_key = self.queue.remove_at_head()
del self.mapping[removed_key] def merge(self, one, two):
else: # decrement capacity
self.capacity -= 1 dummy = merged = ListNode(None)
# Maintain a sorted part of the list. For each next node, find its correct location by iterating along sorted section. merged.next = one or two # add remaining list
# Time - O(n**2)
# Space - O(1) return dummy.next
:rtype: str
class Solution(object): """
def maxPoints(self, points): words = s.split()
""" return " ".join(words[::-1])
:type points: List[Point]
:rtype: int
""" # python_1_to_1000/152_Maximum_Product_Subarray.py - m
if len(points) <= 2:
return len(points) _author_ = 'jake'
_project_ = 'leetcode'
overall_max = 2
# https://leetcode.com/problems/maximum-product-subarray/
for i, point in enumerate(points): # for each point # Find the contiguous subarray within an array (containing at least one number) which has the largest product.
gradients = defaultdict(int) # key is gradient, value is nb lines involving point with this gradient # Calculate the most positive and most negative subarray products ending at each element.
max_points = 1 # point is on every line # Either the element alone or multiplied by previous most positive or most negative.
# Time - O(n)
for point_2 in points[i+1:]: # check all # Space - O(1)
# python_1_to_1000/153_Find_Minimum_in_Rotated_Sorted_Array.py - m
# Push numbers onto stack. Apply operators to top 2 members of stack and push back result. # If right element is less than mid element, min mist be to right of mid. Else min mist be mid or left.
# Faster but less concise without using eval(). # Time - O(log n)
# Time - O(n) # Space - O(1)
# Space - O(n)
class Solution(object):
class Solution(object): def findMin(self, nums):
def evalRPN(self, tokens): """
""" :type nums: List[int]
:type tokens: List[str] :rtype: int
:rtype: int """
""" left = 0
ops = {'+', '-', '/', '*'} right = len(nums)-1
stack = []
while left < right:
for token in tokens:
if nums[left] <= nums[right]: # not rotated, left is min
if token in ops: break
right = stack.pop()
left = stack.pop() mid = (left + right) // 2
if token == '/': if nums[right] < nums[mid]: # min must be on right of mid
stack.append(int(left / float(right))) # round down left = mid + 1
else: else: # nums[right] > nums[mid]
stack.append((eval(str(left) + token + str(right)))) right = mid # min must be mid or on left
else: # nums[right] != nums[mid] because loop terminated if left == right and if right == left + 1 then
stack.append(int(token)) # mid == left and since nums are unique num[left] != nums[right]
# python_1_to_1000/154_Find_Minimum_in_Rotated_Sorted_Array_II.py - h
# python_1_to_1000/151_Reverse_Words_in_a_String.py - m
_author_ = 'jake'
_author_ = 'jake' _project_ = 'leetcode'
_project_ = 'leetcode'
# https://leetcode.com/problems/find-minimum-in-rotated-sorted-array-ii/
# https://leetcode.com/problems/reverse-words-in-a-string/ # Follow up for "153 Find Minimum in Rotated Sorted Array": What if duplicates are allowed?
# Given an input string, reverse the string word by word.
# As per problem 153 except if nums[left] == nums[right] == nums[mid] must search both left and right.
# Parse int a list of words by spaces, reverse word list and recombine with spaces. # Time - O(n)
# Time - O(n) # Space - O(1)
# Space - O(n)
class Solution(object):
class Solution(object): def findMin(self, nums):
def reverseWords(self, s): """
""" :type nums: List[int]
:type s: str :rtype: int
""" # class TreeNode(object):
left, right = 0, len(nums)-1 # def __init__(self, x):
# self.val = x
while left < right: # self.left = None
# self.right = None
if nums[left] < nums[right]: # already sorted
break class Solution(object):
def upsideDownBinaryTree(self, root):
mid = (left + right) // 2 """
:type root: TreeNode
if nums[right] < nums[mid]: :rtype: TreeNode
left = mid + 1 # discontinuity on RHS of mid """
elif nums[right] > nums[mid] or nums[left] > nums[mid]: if not root or not root.left: # if no left then no right, leaf
right = mid # discontinuity is mid or LHS return root
else: # nums[right] == nums[mid] == nums[left]
left += 1 new_root = self.upsideDownBinaryTree(root.left) # recurse left
right -= 1 node = new_root
while node.right: # traverse as far right as possible
return nums[left] node = node.right
node.left = root.right
# python_1_to_1000/155_Min_Stack.py - m node.right = root
root.left = None
_author_ = 'jake' root.right = None
_project_ = 'leetcode'
return new_root
# https://leetcode.com/problems/min-stack/
# Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.
# push(x) -- Push element x onto stack. # python_1_to_1000/157_Read_N_Characters_Given_Read4.py
# pop() -- Removes the element on top of the stack.
# top() -- Get the top element. _author_ = 'jake'
# getMin() -- Retrieve the minimum element in the stack. _project_ = 'leetcode'
# Main stack has all items, mins stack has items less than or equal to previous min. # https://leetcode.com/problems/read-n-characters-given-read4/
# Note : no error handling for empty stack required # The API: int read4(char *buf) reads 4 characters at a time from a file.
# Time - O(1) # The return value is the actual number of characters read. Eg, it returns 3 if only 3 characters are left in the file.
# Space - O(n) # By using the read4 API, implement the function int read(char *buf, int n) that reads n characters from the file.
class MinStack(object): # Read up to 4 chars into buf4 and copy to buf (which is modified in-place).
# Time - O(n)
def __init__(self): # Space - O(n)
"""
initialize your data structure here. # The read4 API is already defined for you.
""" # @param buf, a list of characters
self.main = [] # @return an integer
self.mins = [] def read4(buf):
pass
def push(self, x):
""" class Solution:
:type x: int def read(self, buf, n):
:rtype: void
""" total_chars, last_chars = 0, 4
self.main.append(x)
if not self.mins or x <= self.mins[-1]: while last_chars == 4 and total_chars < n:
self.mins.append(x)
buf4 = [""] * 4 # temporary buffer
def pop(self): last_chars = min(read4(buf4), n - total_chars)
""" buf[total_chars:total_chars+last_chars] = buf4
:rtype: void total_chars += last_chars
"""
item = self.main.pop() return total_chars
if item == self.mins[-1]:
self.mins.pop()
# python_1_to_1000/158_Read_N_Characters_Given_Read4_II_-_Call_multiple_times.py - h
def top(self):
""" _author_ = 'jake'
:rtype: int _project_ = 'leetcode'
"""
return self.main[-1] # https://leetcode.com/problems/read-n-characters-given-read4-ii-call-multiple-times/
# The API: int read4(char *buf) reads 4 characters at a time from a file.
def getMin(self): # The return value is the actual number of characters read.
""" # By using the read4 API, implement the function int read(char *buf, int n) that reads n characters from the file.
:rtype: int # The read function may be called multiple times.
"""
return self.mins[-1] # Use a double-linked list to store any characters read by read4 but not required. Use those characters first
# on the next call of read().
# Time - O(n)
# python_1_to_1000/156_Binary_Tree_Upside_Down.py - m # Space - O(n)
# Base case for recursion is a leaf node or None. Recursively process left subtree, find rightmost path, add previous class Solution(object):
# right on left and previous root on right. def __init__(self):
# Time - O(n) self.leftover = deque() # store chars read by read4 but not added previous buf
# Space - O(1)
def read(self, buf, n):
# Definition for a binary tree node. """
# https://leetcode.com/problems/one-edit-distance/
# Given two strings s and t, determine if they are both one edit distance apart.
# python_1_to_1000/160_Intersection_of_Two_Linked_Lists.py # If same lengths find the one different char (replacement edit) and test all else are same.
# If length diff of 1, find the extra char in longer and check all else is the same.
_author_ = 'jake' # Time - O(n)
_project_ = 'leetcode' # Space - O(1)
# python_1_to_1000/163_Missing_Ranges.py # python_1_to_1000/165_Compare_Version_Numbers.py - m
# https://leetcode.com/problems/missing-ranges/ # https://leetcode.com/problems/compare-version-numbers/
# Given a sorted integer array where elements are in the inclusive range [lower, upper], return its missing ranges. # Compare two version numbers version1 and version2.
# For example, given [0, 1, 3, 50, 75], lower = 0 and upper = 99, return ["2", "4->49", "51->74", "76->99"]. # If version1 > version2 return 1, if version1 < version2 return -1, otherwise return 0.
# You may assume that the version strings are non-empty and contain only digits and the . character.
# Track the last number seen. If num == last_seen+2 then last_seen+1 is the start and end of a missing range. # The . character does not represent a decimal point and is used to separate number sequences.
# If num > last_seen+2 then inclusive range last_seen+1 to num-1 is missing. Update last_seen. Do nothing if
# num is last_seen or last_seen+1 since nothing is missing. # Split by '.' and pad shorter list with [0]. Then compare each section.
# Time - O(n) # Time - O(n)
# Space - O(n) # Space - O(n)
for num in nums: for i1, i2 in itertools.zip_longest(v1, v2, fillvalue=0): # pad shorter with zeros
if num == last_seen + 2: if i1 > i2:
missing.append(str(last_seen+1)) return 1
elif num > last_seen + 2: if i1 < i2:
missing.append(str(last_seen+1) + '->' + str(num-1)) return -1
last_seen = num
return 0 # all version components are same
return missing
# python_1_to_1000/166_Fraction_to_Recurring_Decimal.py - m
# Find the initial integer part then repeatedly multiply by 10, divide by denominator and calculate remainder. If column = deque() # faster than list for appendleft()
# same remainder repeats there is a cycle. while n > 0:
n, output = divmod(n-1, 26)
class Solution(object): column.appendleft(output)
def fractionToDecimal(self, numerator, denominator):
""" return "".join([chr(i+ord('A')) for i in column])
:type numerator: int
:type denominator: int
:rtype: str
"""
if denominator == 0: # python_1_to_1000/169_Majority_Element.py
return None
decimal = [] # store result as a list _author_ = 'jake'
if numerator * denominator < 0: # negative sign _project_ = 'leetcode'
decimal.append('-')
# https://leetcode.com/problems/majority-element/
output, remainder = divmod(abs(numerator), abs(denominator)) # divide and modulo combined # Given an array of size n, find the majority element. The majority element appears more than [n/2] times.
decimal.append(str(output)) # You may assume that the array is non-empty and the majority element always exist in the array.
if remainder == 0:
return "".join(decimal) # When the count is zero, the next element becomes the candidate. When an element is the same as the candidate,
# increment the count, else decrement the count.
decimal.append('.') # Time - O(n)
seen = {} # key is remainder, value is index in decimal # Space - O(1)
if count == 0:
candidate = num
# python_1_to_1000/167_Two_Sum_II_-_Input_array_is_sorted.py - m
if candidate == num:
_author_ = 'jake' count += 1
_project_ = 'leetcode' else:
count -= 1
# https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/
# Given an array of integers that is already sorted in ascending order, find an ordered pair of indices of two numbers return candidate
# such that they add up to a specific target number.
# Please note that your returned answers (both index1 and index2) are not zero-based.
# You may assume that each input would have exactly one solution. # python_1_to_1000/170_Two_Sum_III_-_Data_structure_design.py
# Start pointers at both ends of array. Increment left if sum is too low or decrement right if sum is too high. _author_ = 'jake'
# Time - O(n) _project_ = 'leetcode'
# Space - O(1)
# https://leetcode.com/problems/two-sum-iii-data-structure-design/
class Solution(object): # Design and implement a TwoSum class. It should support the following operations: add and find.
def twoSum(self, numbers, target): # add - Add the number to an internal data structure.
""" # find - Find if there exists any pair of numbers which sum is equal to the value.
:type numbers: List[int]
:type target: int # Use a dictionary to store each number and whether it has been added multiple times. To find, for each num in
:rtype: List[int] # dictionary look for the difference between target value and that num, or for the num to be duplicated if it
""" # is half of the target value.
left, right = 0, len(numbers)-1 # Time - O(1) to add, O(n) to find
# Space - O(n)
while True:
class TwoSum(object):
pair_sum = numbers[left] + numbers[right]
if pair_sum == target: def __init__(self):
return [left+1, right+1] """
initialize your data structure here
if pair_sum < target: """
left += 1 self.nums = {} # key is num, value is True if num is duplicated else False
else:
right -= 1 def add(self, number):
"""
Add the number to an internal data structure.
# python_1_to_1000/168_Excel_Sheet_Column_Title.py :rtype: nothing
"""
_author_ = 'jake' self.nums[number] = number in self.nums # False for first occurence, True for multiple occurrences
_project_ = 'leetcode'
def find(self, value):
# https://leetcode.com/problems/excel-sheet-column-title/ """
# Given a positive integer, return its corresponding column title as appear in an Excel sheet. Find if there exists any pair of numbers which sum is equal to the value.
# For example:, 1 -> A, 2 -> B, 3 -> C, ..., 26 -> Z, 27 -> AA :type value: int
:rtype: bool
# Generate characters starting with least significant by calculating remainder of division by 26. """
# Time - O(log n) for num in self.nums:
# Space - O(log n) if value == 2 * num: # need num to be duplicated
if self.nums[num]:
from collections import deque return True
else: # look for difference
class Solution(object): if value - num in self.nums:
def convertToTitle(self, n): return True
""" return False
:type n: int
:rtype: str
"""
# python_1_to_1000/171_Excel_Sheet_Column_Number.py def next(self):
"""
_author_ = 'jake' :rtype: int
_project_ = 'leetcode' """
node = self.stack.pop()
# https://leetcode.com/problems/excel-sheet-column-number/ result = node.val
# Given a column title as appear in an Excel sheet, return its corresponding column number. if node.right:
node = node.right
# For each char, multiply previous result by 26 and add value of char while node:
# Time - O(n) self.stack.append(node)
# Space - O(n) node = node.left
return result
class Solution(object):
def titleToNumber(self, s):
""" # python_1_to_1000/174_Dungeon_Game.py - h
:type s: str
:rtype: int _author_ = 'jake'
""" _project_ = 'leetcode'
result = 0
for c in s: # https://leetcode.com/problems/dungeon-game/
result = result*26 + ord(c) - ord('A') + 1 # The demons had captured the princess (P) and imprisoned her in the bottom-right corner of a dungeon.
return result # The dungeon consists of M x N rooms laid out in a 2D grid. Our valiant knight (K) was initially positioned in the
# top-left room and must fight his way through the dungeon to rescue the princess.
# The knight has an initial health point represented by a positive integer. If at any point his health point drops
# python_1_to_1000/172_Factorial_Trailing_Zeros.py - m # to 0 or below, he dies immediately.
# Some of the rooms are guarded by demons, so the knight loses health (negative integers) upon entering these rooms;
_author_ = 'jake' # other rooms are either empty (0's) or contain magic orbs that increase the knight's health (positive integers).
_project_ = 'leetcode' # In order to reach the princess as quickly as possible, the knight moves only rightward or downward in each step.
# Write a function to determine the knight's minimum initial health so that he is able to rescue the princess.
# https://leetcode.com/problems/factorial-trailing-zeroes/
# Given an integer n, return the number of trailing zeroes in n!. # Dynamic programming. Min health to reach end from any room is health lost/gained in that room + min required
# after moving down or right, floored at 1 since health cannot be zero.
# Every trailing zero is created by a factor of 5 (since there are many more factors of 2 that together make # Time - O(n * m)
# trailing zeroes). Count the numbers in 1..n that are divisible by 5, then those divisible by 25 which have a # Space - O(n + m)
# second factor of 5, then 125 etc ...
# Time - O(log n) class Solution(object):
# Space - O(1) def calculateMinimumHP(self, dungeon):
"""
class Solution(object): :type dungeon: List[List[int]]
def trailingZeroes(self, n): :rtype: int
""" """
:type n: int rows, cols = len(dungeon), len(dungeon[0])
:rtype: int
""" for r in range(rows - 1): # add new final column and row of infinity
zeroes = 0 dungeon[r].append(float('inf'))
power_of_5 = 5 dungeon.append([float('inf') for _ in range(cols + 1)])
while power_of_5 <= n: dungeon[rows - 1].append(1) # final room requires min health of 1
zeroes += n // power_of_5
power_of_5 *= 5 for r in range(rows - 1, -1, -1):
for c in range(cols - 1, -1, -1):
return zeroes dungeon[r][c] = max(1, -dungeon[r][c] + min(dungeon[r+1][c], dungeon[r][c+1]))
return dungeon[0][0]
# python_1_to_1000/173_Binary_Search_Tree_Iterator.py - m
# Time - O(n * k)
_author_ = 'jake' # Space - O(n * k)
_project_ = 'leetcode'
class Solution(object):
# https://leetcode.com/problems/reverse-words-in-a-string-ii/ def maxProfit(self, k, prices):
# Given an input string, reverse the string word by word. A word is defined as a sequence of non-space characters. """
# The input string does not contain leading or trailing spaces and the words are always separated by a single space. :type k: int
:type prices: List[int]
# Revese entire string then reverse each word individually. :rtype: int
# Alternatively use built-in reverse() and reversed() functions. """
# Time - O(n) if k >= len(prices) // 2: # can transact as often as required to get max profit
# Space - O(1) return sum([max(0, prices[i] - prices[i-1]) for i in range(1, len(prices))])
class Solution: # buys[i] is the max profit after i-1 buy/sell transactions and another buy
# @param s, a list of 1 length strings, e.g., s = ['h','e','l','l','o'] # sells[i] is the max profit after i buy/sell transactions
# @return nothing buys, sells = [float('-inf') for _ in range(k + 1)], [0 for _ in range(k + 1)]
def reverseWords(self, s):
for price in prices:
self.reverse(s, 0, len(s)-1) for i in range(1, len(buys)):
s.append(' ') # temporary space to signify end of last word buys[i] = max(buys[i], sells[i-1] - price) # add -price to previous best after i-1 transactions
start = 0 if buys[i] == buys[i-1]: # additional transaction has not increased profit
for i in range(len(s)): break
if s[i] == ' ': sells[i] = max(sells[i], buys[i] + price) # add +price to max after i-1 transactions and another buy
self.reverse(s, start, i-1) # reverse word from start to i-1
start = i+1 # start of next word return max(sells)
s.pop()
# https://leetcode.com/problems/rotate-array/
class Solution2: # Rotate an array of n elements to the right by k steps.
def reverseWords(self, s):
s.reverse() # Reverse entire array, then reverse left k elements and right n-k elements.
s.append(' ') # Alternatively, split after n-k elements and swap slices.
start = 0 # Time - O(n)
for i in range(len(s)): # Space - O(1)
if s[i] == ' ':
s[start:i] = reversed(s[start:i]) class Solution(object):
start = i+1 def rotate(self, nums, k):
s.pop() """
:type nums: List[int]
:type k: int
# python_1_to_1000/187_Repeated_DNA_Sequences.py - m :rtype: void Do not return anything, modify nums in-place instead.
"""
_author_ = 'jake' k %= len(nums)
_project_ = 'leetcode' nums.reverse()
nums[:k] = reversed(nums[:k])
# https://leetcode.com/problems/repeated-dna-sequences/ nums[k:] = reversed(nums[k:])
# All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, for example: "ACGAATTCCG".
# When studying DNA, it is sometimes useful to identify repeated sequences within the DNA. class Solution2(object):
# Write a function to find all the 10-letter-long sequences (substrings) that occur more than once in a DNA molecule. def rotate(self, nums, k):
n = len(nums)
# Store all substrings of length 10 in a set, if substring is duplicated add to result set. k %= n
# Time - O(n) nums[:] = nums[n-k:] + nums[:n-k]
# Space - O(n)
# Dynamic programming. Max profit after i buys = cost + max after i-1 transactions. reversed, bit = 0, 31
# Max profit after i sells = sale price + max after i-1 transactions and additional buy.
while n != 0: right_view = []
if n % 2 == 1: # last bit is set layer = [root]
reversed += 2**bit
bit -= 1 while layer:
n //= 2
right_view.append(layer[-1].val)
return reversed next_layer = []
# BFS layer by layer. Add to result last value found in a layer. def set_island(self, row, col, grid):
# Alternatively, recursively pre-order traverse tracking depth and updating result for each node. if row < 0 or row >= len(grid) or col < 0 or col >= len(grid[0]):
# Time - O(n) return
# Space - O(n) if grid[row][col] != '1':
return
# Definition for a binary tree node. grid[row][col] = '0'
class TreeNode(object): self.set_island(row+1, col, grid)
def __init__(self, x): self.set_island(row-1, col, grid)
self.val = x self.set_island(row, col+1, grid)
self.left = None self.set_island(row, col-1, grid)
self.right = None
class Solution(object):
def rightSideView(self, root): # python_1_to_1000/201_Bitiwse_AND_of_Numbers_Range.py - m
"""
:type root: TreeNode _author_ = 'jake'
:rtype: List[int] _project_ = 'leetcode'
"""
if not root: # https://leetcode.com/problems/bitwise-and-of-numbers-range/
return [] # Given a range [m, n] where 0 <= m <= n <= 2147483647, return the bitwise AND of all numbers in this range, inclusive.
# Starting from the most significant bit that is set in n, compare each bit in n to the equivalent bit in m. # Definition for singly-linked list.
# If both bits are the same, set the same bit in the result to its value in m and n. class ListNode(object):
# Stop when a bit is set differently in m and n. def __init__(self, x):
# When any bit is different, all less significant bits must take on both values of 0 and 1 in the range. self.val = x
# Time - O(log n) self.next = None
# Space - O(1)
class Solution(object):
from math import log def removeElements(self, head, val):
"""
class Solution(object): :type head: ListNode
def rangeBitwiseAnd(self, m, n): :type val: int
""" :rtype: ListNode
:type m: int """
:type n: int dummy = prev = ListNode(None) # dummy in case head is deleted
:rtype: int dummy.next = head
"""
if m == 0: while head:
return 0
result = 0 if head.val == val:
prev.next, head.next, head = head.next, None, head.next
bit = int(log(n, 2)) # highest bit that is set in n else:
prev, head = head, head.next
while bit >= 0 and ((m & (1 << bit)) == (n & (1 << bit))):
if (m & (1 << bit)): # if this bit is set return dummy.next
result += 2**bit
bit -= 1
# python_1_to_1000/204_Count_Primes.py - m
return result
_author_ = 'jake'
_project_ = 'leetcode'
# python_1_to_1000/202_Happy_Number.py
# https://leetcode.com/problems/count-primes/
_author_ = 'jake' # Count the number of prime numbers less than a non-negative number, n.
_project_ = 'leetcode'
# Sieve numbers. Assume all are prime and eliminate those with factors.
# https://leetcode.com/problems/happy-number/ # Time - O(n***3/2)
# Write an algorithm to determine if a number is "happy". # Space - O(n)
# A happy number is a number defined by the following process: Starting with any positive integer,
# replace the number by the sum of the squares of its digits, and repeat the process until the number equals 1 class Solution(object):
# (where it will stay), or it loops endlessly in a cycle which does not include 1. Those numbers for which this def countPrimes(self, n):
# process ends in 1 are happy numbers. """
:type n: int
# Fast and slow pointers increment to the next sum of square digits. If in a cycle pointers will converge at :rtype: int
# a value other than 1, if no cycle pointers will both be 1. """
# Alternatively, if n == 4 then we are in a cycle. See https://en.wikipedia.org/wiki/Happy_number sieve = [False, False] + [True for _ in range(n-2)] # 0 and 1 are not prime
# Time - O(log n)
# Space - O(1) for i in range(2, int(n**0.5) + 1): # end at sqrt since any j not prime must have a factor <= sqrt(j)
class Solution2(object): # Store a mapping from chars of s to chars of t. If a char in s is already in mapping then check that the char in t
def isHappy(self, n): # is same as previously observed. Check also that a new mapping of char in s is not to a char in t already mapped.
""" # Time - O(n)
:type n: int # Space - O(n)
:rtype: bool
""" class Solution(object):
while True: def isIsomorphic(self, s, t):
if n == 1: """
return True :type s: str
if n == 4: :type t: str
return False :rtype: bool
n = sum([int(c)*int(c) for c in str(n)]) """
if len(s) != len(t):
return False
# python_1_to_1000/203_Remove_Linked_List_Elements.py s_to_t = {}
t_mapped = set()
_author_ = 'jake'
_project_ = 'leetcode' for cs, ct in zip(s, t):
# https://leetcode.com/problems/remove-linked-list-elements/ if cs in s_to_t:
# Remove all elements from a linked list of integers that have value val. if s_to_t[cs] != ct:
return False
# Iterate along list, cutting out nodes with val. elif ct in t_mapped:
# Time - O(n) return False
# Space - O(1) s_to_t[cs] = ct
t_mapped.add(ct)
return True # Node stores dictionary mapping letters to child nodes. Array would use fixed space regardless of actual nb children.
# Note that node does not explicitly store letter.
# Time - O(n) to create where n is total length of all words, O(k) to search where k is length of word.
# Space - O(n)
# python_1_to_1000/206_Reverse_Linked_List.py
class TrieNode(object):
_author_ = 'jake' def __init__(self):
_project_ = 'leetcode' """
Initialize your data structure here.
# https://leetcode.com/problems/reverse-linked-list/ """
# Reverse a singly linked list. self.children = {} # mapping from letter to child TrieNodes
self.terminal = False # flag indicates whole word
# Iterative resvers. Alternatively, use recursion.
# Time - O(n) class Trie(object):
# Space - O(1)
def __init__(self):
# Definition for singly-linked list. self.root = TrieNode()
class ListNode(object): self.root.terminal = True # empty string is a whole word
def __init__(self, x):
self.val = x def insert(self, word):
self.next = None """
Inserts a word into the trie.
class Solution(object): :type word: str
def reverseList(self, head): :rtype: void
""" """
:type head: ListNode node = self.root
:rtype: ListNode for c in word:
""" if c not in node.children: # create a node if it does not exist
reversed = None node.children[c] = TrieNode()
while head: node = node.children[c]
next = head.next node.terminal = True # set to True at end of word
head.next = reversed
reversed = head def search(self, word):
head = next """
return reversed Returns if the word is in the trie.
:type word: str
:rtype: bool
# python_1_to_1000/207_Course_Schedule.py - m """
node = self.root
_author_ = 'jake' for c in word:
_project_ = 'leetcode' if c in node.children:
node = node.children[c]
# https://leetcode.com/problems/course-schedule/ else:
# There are a total of n courses you have to take, labeled from 0 to n - 1. return False
# Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed return node.terminal # only True if terminal
as a pair: [0,1]
# Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses? def startsWith(self, prefix):
"""
# Topological sort. Find nodes with no dependencies. Remove outgoing edges from each such node. Repeat until Returns if there is any word in the trie
# no node has no dependencies. that starts with the given prefix.
# Time - O(m + n), edges + nodes :type prefix: str
# Space - O(m + n) :rtype: bool
"""
from collections import defaultdict node = self.root
for c in prefix:
class Solution(object): if c in node.children:
def canFinish(self, numCourses, prerequisites):