from simple_unittest import test def twoSum(nums, target): lookup_cache = {} for i, a in enumerate(nums): b = target - a if b in lookup_cache: return [lookup_cache[b], i] else: lookup_cache[a] = i return [] test('empty', twoSum([], 0), []) test('one', twoSum([1, 1], 2), [0, 1]) test('[2, 7, 11, 15] -> 9', twoSum([2, 7, 11, 15, 9], 9), [0, 1]) test('[0, 1] -> 1', twoSum([0, 1], 1), [0, 1]) test('[7, 11, 15] -> 26', twoSum([7, 11, 15], 26), [1, 2])
from simple_unittest import test def strings_mix(s1, s2): sortedS1 = sorted(s1.lower()) sortedS2 = sorted(s2.lower()) iS1 = 0 iS2 = 0 cS1 = 0 cS2 = 0 for c in sortedS1: if c.isalpha(): return orderedDictS1 test('', strings_mix("my&friend&Paul has heavy hats! &", "my friend John has many many friends &"), "2:nnnnn/1:aaaa/1:hhh/2:mmm/2:yyy/2:dd/2:ff/2:ii/2:rr/=:ee/=:ss")
from simple_unittest import test def flatten(array): result = [] for i in array: if isinstance(i, int): result.append(i) else: result.extend(flatten(i)) return result test('[0, [1, [2, [3]]]]', flatten([0, [1, [2, [3]]]]), [0, 1, 2, 3]) test('[0]', flatten([0]), [0]) test('[[1,1], 0, [1, 1]]', flatten([[1, 1], 0, [1, 1]]), [1, 1, 0, 1, 1])
from simple_unittest import test # 1. sorted anagrams are the same! def anagrams(strs): result = [] resultSorted = {} for s in strs: sortedS = "".join(sorted(s)) if sortedS in resultSorted: resultSorted[sortedS].append(s) else: resultSorted[sortedS] = [s] for key in resultSorted: result.append(resultSorted[key]) return result test('leetcode example', anagrams( ["eat","tea","tan","ate","nat","bat"] ), [ ["ate", "eat", "tea"], ["nat", "tan"], ["bat"] ])
from simple_unittest import test # check if each next element is higher or lower # if its higher buy at x and then sell at next element get the profit def buySellStock(nums): maxProfit = 0 for i in range(len(nums) - 1): if nums[i + 1] > nums[i]: maxProfit += nums[i + 1] - nums[i] return maxProfit test('leetcode example', buySellStock([7, 1, 5, 3, 6, 4]), 7) test('leetcode example 1', buySellStock([1, 2, 3, 4, 5]), 4) test('leetcode example 2', buySellStock([7, 6, 4, 3, 1]), 0)
# 2nd observation - only 1 with 0 is possible to get True from simple_unittest import test def isHappy(n): cache = {} return recHappyNumber(n, cache) def recHappyNumber(n, cache): if n in cache: return False newNumber = 0 for x in str(n): if x == '0': continue; newNumber += pow(int(x),2) if newNumber == 1: return True cache[n] = True return recHappyNumber(newNumber, cache) test('19', isHappy(19), True)
# to remove duplicates we start from 2 to n for c_i in range(b_i + 1, length): a = nums[a_i] b = nums[b_i] c = nums[c_i] if a + b + c == 0: result.append([a, b, c]) return result def threeSum(nums): length = len(nums) if length < 3: return [] result = threeSum_sorted(nums, length) unique_lst = [] [unique_lst.append(sub) for sub in result if not unique_lst.count(sub)] return unique_lst test('two elements', threeSum([1, 2]), []) test('empty', threeSum([]), []) print threeSum([-1, 0, 1, 2, -1, -4])
if nums[midpoint] > nums[midpoint + 1]: return midpoint + 1 # just check if we accidentaly have found pivot already will also cover cases like [7,0] if nums[midpoint - 1] > nums[midpoint]: return midpoint # if mid is greater than start it means that pivot is to the left if nums[midpoint] > nums[start]: return findPivot(nums, midpoint, end) # otherwise pivot is to the right else: return findPivot(nums, start, midpoint) test('find pivot 1', findPivot([4, 5, 6, 7, 0, 1, 2], 0, 7), 4) test('find pivot 2', findPivot([4, 5, 6, 7, 8, 0, 1, 2], 0, 8), 5) test('find pivot 3', findPivot([2, 1], 0, 1), 1) test('find pivot 3', findPivot([5, 1, 3], 0, 2), 1) def quickSearch(nums, start, end, target): # we didn't find the index if start == end: return -1 if target == nums[start]: return start if target == nums[end]: return end
while carry and current_index >= 0: current_number = array[current_index] if current_number != 9: carry = False current_number += 1 else: carry = True if not carry: array[current_index] = current_number else: array[current_index] = 0 current_index -= 1 if carry: return [1] + array return array test('[]', plus_one([]), []) test('[0]', plus_one([0]), [1]) test('[1, 2, 3]', plus_one([1, 2, 3]), [1, 2, 4]) test('[1, 2, 9]', plus_one([1, 2, 9]), [1, 3, 0]) test('[1, 9, 9]', plus_one([1, 9, 9]), [2, 0, 0]) test('[1, 0, 0]', plus_one([1, 0, 0]), [1, 0, 1]) test('[9, 9, 9]', plus_one([9, 9, 9]), [1, 0, 0, 0]) test('[9]', plus_one([9]), [1, 0]) test('[9, 9]', plus_one([9, 9]), [1, 0, 0])
if len(s) <= 0: return 0 if len(s) == 1: return 1 found = set() max_length = 0 for c in s: if c not in found: found.add(c) else: if len(found) > max_length: max_length = len(found) found.remove(c) if len(found) > max_length: max_length = len(found) return max_length test('', length_of_longest_substring(''), 0) test('a', length_of_longest_substring('a'), 1) test('abcabcbb', length_of_longest_substring('abcabcbb'), 3) test('abcadbcbb', length_of_longest_substring('abcadbcbb'), 4) test('bbbbb', length_of_longest_substring('bbbbb'), 1) test('pwwkew', length_of_longest_substring('pwwkew'), 3) test('abcd', length_of_longest_substring('abcd'), 4)
max = cur return max # 1. if len recipe > len available then 0 as its clear we lack ingredients # most basic idea # go through each recipe key check if it exissts # if not -> 0, # if exists - divide available by recipe - set it as max doable # go to next key -> if max < previous max new max it is # this would then be O(n) as we only go through available list and checking another one is O(1) recipe = {"flour": 500, "sugar": 200, "eggs": 1} available = {"flour": 1200} test('len different', cakes(recipe, available), 0) recipe = {'pears': 61, 'butter': 54, 'sugar': 81} available = { 'flour': 3190, 'butter': 34, 'cream': 8955, 'crumbles': 3153, 'pears': 4032, 'sugar': 2134, 'apples': 5238, 'oil': 8597, 'nuts': 1870, 'cocoa': 5292 } test('failing test', cakes(recipe, available), 0)
from simple_unittest import test # we can go O(n) through list and put them in hash # so that if x is counted then in hash there should be key x+1 # this gives us O(1) check if key exists def countingElements(nums): mappedValues = {} counter = 0 # O(n) to put values into map for n in nums: mappedValues[n] = True # O(n) to check if n+1 exists for n in nums: if n + 1 in mappedValues: counter += 1 # in the end its O(n) return counter test('leetcode example', countingElements([1, 2, 3]), 2) test('leetcode example1', countingElements([1, 1, 3, 3, 5, 5, 7, 7]), 0) test('leetcode example2', countingElements([1, 3, 2, 3, 5, 0]), 3) test('leetcode example3', countingElements([1, 1, 2, 2]), 2) test('leetcode example3', countingElements([1, 1, 1, 2, 2]), 3)
# 5 iteration the value is 4 sum is 4 so maxSum is 4 def linearMaxSubArray(nums): if len(nums) == 0: return 0 if len(nums) == 1: return nums[0] # has to be -maxint to prevent situation when maxSum is higher that value in nums # rost case value in nums is equal to -sys.maxint so then we can return -sys.maxint maxSum = -sys.maxint currentSum = 0 for i in nums: currentSum += i if currentSum <= 0: maxSum = max(maxSum, i) currentSum = 0 else: if maxSum < currentSum: maxSum = currentSum return maxSum test('leetcode example', divideAndConquerSubArray([-2, 1, -3, 4, -1, 2, 1, -5, 4]), 6) # with all minuses we just need to return lowest value in the array test('leetcode all minuses', divideAndConquerSubArray([-2, -1, -3, -4, -1]), -1)
return '' not_found_end = True while not_found_end and index < len(smallest_word): for word_index in range(1, len(strs)): if index >= len(strs[word_index]): not_found_end = False break if strs[word_index][index] != strs[0][index]: not_found_end = False break if not_found_end: index += 1 return smallest_word[0:index] test('basic', longestCommonPrefix(['flower', 'flow', 'flight']), 'fl') test('fail', longestCommonPrefix(['a', 'ac']), 'a') test('fail', longestCommonPrefix(['caaa', 'aaaa']), '') test('fail', longestCommonPrefix(['a']), 'a') test('fail', longestCommonPrefix(['', 'b']), '') test('none', longestCommonPrefix(['dog', 'racecar', 'car']), '') test('long', longestCommonPrefix(['aaaaaaaaaaaaaaaaa', 'aaaaaaaaaaaa', 'aaaaaaaa']), 'aaaaaaaa') test('empty list', longestCommonPrefix([]), '')
from simple_unittest import test def validParenthness(string): stack = [] if len(string) <= 0: return True for c in string: if c == "(": stack.append("(") if c == ")": if len(stack) <= 0: return False stack.pop() return len(stack) <= 0 test('Empty', validParenthness(""), True) test('()', validParenthness("()"), True) test(')(()))', validParenthness(")(()))"), False) test('((()))', validParenthness("((()))"), True) test(')))(((', validParenthness(")))((("), False) test('(', validParenthness("("), False) test('(())((()())())', validParenthness("(())((()())())"), True)
grid = flipCol(x, grid) for r in range(height): row = grid[r] string_ints = [str(int) for int in row] bin = int(''.join(string_ints), 2) maxSum += bin return maxSum def flipCol(colNr, grid): for x in range(len(grid)): grid[x][colNr] = int(not grid[x][colNr]) return grid def flipRow(rowNr, grid): row = grid[rowNr] for i in range(len(row)): row[i] = int(not row[i]) return grid def printN(grid): for i in range(len(grid)): print(grid[i]) test('basic', scoreFlipMatrix([[0, 0, 1, 1], [1, 0, 1, 0], [1, 1, 0, 0]]), 39)
if root.value < min_val or root.value > max_val: return False return is_bst_valid_rec(root.left, min_val, root.value) and is_bst_valid_rec( root.right, root.value, max_val) def is_bst_valid(root): #return is_bst_valid_rec(root, float('-inf'), float('inf')) return is_bst_valid_inorder(root) bst_tree = bst(height=3) print(bst_tree) test('valid_bst', is_bst_valid(bst_tree), True) non_bst = tree(height=3) print(non_bst) test('invalid bst - simple', is_bst_valid(non_bst), False) non_bst_complex = Node(4) non_bst_complex.left = Node(2) non_bst_complex.left.left = Node(1) non_bst_complex.left.right = Node(3) non_bst_complex.left.right.left = Node(1) #non_bst_complex.left.right.right = Node(6) non_bst_complex.right = Node(5)
from simple_unittest import test def maskify(number): if len(number) <= 4: return number return ''.join((["#"] * (len(number) - 4))) + number[len(number) - 4:] test('', maskify(''), '') test('1', maskify('1'), '1') test('123456789', maskify('123456789'), '#####6789')
from simple_unittest import test def product(array): return array test('[5,6,10]', product([5, 6, 10]), [60, 50, 30])
if n % 2 != 0: val = myPow(x * x, (abs(n) - 1) / 2) else: val = myPow(x * x, abs(n / 2)) if n % 2 != 0: val *= x if n < 0: val = 1.0 / val if x < 0 and n % 2 != 0: val = -abs(val) return val test('if n 0 then return 1', myPow(1, 0), 1) test('if n 1 then return x', myPow(100, 1), 100) test('2^2', myPow(2, 2), 4) test('2^3', myPow(2, 3), 8) test('2^4', myPow(2, 4), 16) test('3^3', myPow(3, 3), 27) test('2^-1', myPow(2, -1), 0.5) test('2^-2', myPow(2, -2), 0.25) test('2^-3', myPow(2, -3), 0.125) test('2^-4', myPow(2, -4), 0.0625) test('-4^2', myPow(-4, 2), 16) test('2^-5', myPow(2, -5), 0.03125) test('edge', myPow(-13.62608, 3), -2529.955504)
nums.pop() else: nums[index_left], nums[index_right] = nums[index_right], nums[ index_left] nums.pop() index_right -= 1 index_left += 1 return len(nums) array = [] val = 0 expected_array = [] expected_len = 0 test('1. if nums empty then empty', removeElement(array, val), expected_len) test('array ', array, expected_array) array = [1, 2] val = 2 expected_array = [1] expected_len = 1 test('2. if nums empty then empty', removeElement(array, val), expected_len) test('array ', array, expected_array) array = [1, 2, 3] val = 2 expected_array = [1, 3] expected_len = 2 test('3. if nums empty then empty', removeElement(array, val), expected_len) test('array ', array, expected_array)
roman_dict = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000} substraction_pairs = set(['IV', 'IX', 'XL', 'XC', 'CD', 'CM']) def roman_to_int(roman_string): result = 0 i = 0 while i < len(roman_string): if i + 1 < len(roman_string) and roman_string[i] + roman_string[ i + 1] in substraction_pairs: result += (roman_dict[roman_string[i + 1]] - roman_dict[roman_string[i]]) i += 2 else: result += roman_dict[roman_string[i]] i += 1 return result test('III', roman_to_int('III'), 3) test('XII', roman_to_int('XII'), 12) test('XXII', roman_to_int('XXII'), 22) test('XXVII', roman_to_int('XXVII'), 27) test('IV', roman_to_int('IV'), 4) test('LVIII', roman_to_int('LVIII'), 58) test('MCMXCIV', roman_to_int('MCMXCIV'), 1994)
from simple_unittest import test # time - O(n) # space - O(1) def move_zeroes(array): if len(array) <= 0: return [] counter = 0 for x in range(len(array)): if array[x] != 0: array[counter] = array[x] counter += 1 while counter < len(array): array[counter] = 0 counter += 1 test('basic', move_zeroes([]), []) test('basic', move_zeroes([0, 1, 0, 3, 12]), [1, 3, 12, 0, 0]) test('basic', move_zeroes([0, 0, 0, 0, 0]), [0, 0, 0, 0, 0]) test('basic', move_zeroes([0, 0, 0, 0, 1]), [1, 0, 0, 0, 0]) test('basic', move_zeroes([1, 0, 0, 0, 1]), [1, 1, 0, 0, 0]) test('basic', move_zeroes([1, 1, 1, 1, 1]), [1, 1, 1, 1, 1]) test('basic', move_zeroes([0, 0, 1, 1, 1]), [1, 1, 1, 0, 0]) test('basic', move_zeroes([0, 1, 0]), [1, 0, 0]) test('basic', move_zeroes([1, 0, 1, 0, 1]), [1, 1, 1, 0, 0]) test('basic', move_zeroes([1, 0, 2, 0, 3, 0, 4, 0, 0, 5]), [1, 2, 3, 4, 5, 0, 0, 0, 0 ,0])
# index - char # value - frequency d = {} for i in set(value): d[i] = value.count(i) helper = set() # iterate from lowest frequency to the highest for freq in sorted(d.values(), reverse=True): # try to insert frequency to set and look for space while freq in helper: freq -= 1 minDel += 1 # if the freq is 0 then we had to remove all the chars # if not then this is unique frequency if freq: helper.add(freq) return minDel test('aab', minDelFrequency2("aab"), 0) test('abcabc', minDelFrequency2("abcabc"), 3) test('aaabbbcc', minDelFrequency2("aaabbbcc"), 2) test('aaabbbccc', minDelFrequency2("aaabbbccc"), 3) test('ceabaacb', minDelFrequency2("ceabaacb"), 2) test('abbcccddddeeeeffff', minDelFrequency2("abbcccddddeeeeffff"), 8) test( 'big', minDelFrequency2( "abcdefghijklmnopqrstuvwxwzabcdefghijklmnopqrstuvwxwzabcdefghijklmnopqrstuvwxwzabcdefghijklmnopqrstuvwxwzabcdefghijklmnopqrstuvwxwzabcdefghijklmnopqrstuvwxwzabcdefghijklmnopqrstuvwxwzabcdefghijklmnopqrstuvwxwzabcdefghijklmnopqrstuvwxwzabcdefghijklmnopqrstuvwxwzabcdefghijklmnopqrstuvwxwzabcdefghijklmnopqrstuvwxwzabcdefghijklmnopqrstuvwxwzabcdefghijklmnopqrstuvwxwzabcdefghijklmnopqrstuvwxwzabcdefghijklmnopqrstuvwxwzabcdefghijklmnopqrstuvwxwzabcdefghijklmnopqrstuvwxwzabcdefghijklmnopqrstuvwxwzabcdefghijklmnopqrstuvwxwzabcdefghijklmnopqrstuvwxwzabcdefghijklmnopqrstuvwxwzabcdefghijklmnopqrstuvwxwzabcdefghijklmnopqrstuvwxwzabcdefghijklmnopqrstuvwxwzabcdefghijklmnopqrstuvwxwz" ), 276)
from simple_unittest import test # idea will be simple # count number of zeroes and move non zero integers by this number to the left # and put zero in the value if you move it def moveZeroes(nums): numZeroes = 0 for i in range(len(nums)): if nums[i] == 0: numZeroes += 1 elif numZeroes > 0: nums[i - numZeroes] = nums[i] nums[i] = 0 return nums test('leetcode example', moveZeroes([0,1,0,3,12]), [1,3,12,0,0])
# brute force - go through each item and count them to dict then go through dict and find items with 1 element # this would give O(n) as this would be # pass through array O(n) + pass through dict O(n) # but there is a solution without additional memory # so we could modify existing input? by moving single digit to somewhere inside the original nums array # the fact that it can either appar once or twice is significant # how can we use twice? # looked up on the net and you can use xor for it from simple_unittest import test def singleNumber(nums): result = 0 if len(nums) == 0: return None for num in nums: result ^= num return result test('2 2 1 -> 1', singleNumber([2, 2, 1]), 1) test('4 1 2 1 2 -> 4', singleNumber([4, 1, 2, 1, 2]), 4) test('empty', singleNumber([]), None)
for i, x in enumerate(nums): result[i] = totalMultiplication / x return result # 3. without division # product to the left and right and multiply them def productOfArrayWithoutDivision(nums): l = len(nums) result, left, right = [0] * l, [0] * l, [0] * l left[0] = 1 for i in range(1, l): left[i] = nums[i - 1] * left[i - 1] right[l - 1] = 1 for i in reversed(range(l -1)): right[i] = nums[i + 1] * right[i + 1] for i in range(l): result[i] = left[i] * right[i] return result test('leetcode example', productOfArrayWithoutDivision([1,2,3,4]), [24,12,8,6]) test('with negative value', productOfArrayWithoutDivision([-1,2,3,4]), [24,-12,-8,-6]) test('with 1 zero', productOfArrayWithoutDivision([0,2,3,4]), [24,0,0,0]) test('with 2 zeros', productOfArrayWithoutDivision([0,2,0,4]), [0,0,0,0])
from simple_unittest import test def combination_sum(candidates, target): if target <= 0: return [] sorted_candidates = sorted(candidates, reverse=True) result = [] for x in sorted_candidates: if x == target: result.append([x]) if x < target: leftovers = combination_sum(candidates, target - x) if len(leftovers): for i in leftovers: result.append(i + [x]) else: continue return [] test('[2, 3, 6, 7]', combination_sum([2, 3, 6, 7], 7), [[7], [2, 2, 3]]) test('[2, 3, 5]', combination_sum([2, 3, 5], 8), [[2, 2, 2, 2], [2, 3, 3], [3, 5]])
from simple_unittest import test # A pangram is a sentence that contains every single letter of the alphabet at least once. For example, the sentence "The quick brown fox jumps over the lazy dog" is a pangram, because it uses the letters A-Z at least once (case is irrelevant). # Given a string, detect whether or not it is a pangram. Return True if it is, False if not. Ignore numbers and punctuation. def is_pangram(sentence): letters_count = 26 s = set() # put char to set to make it unique then sum all the chars and check count of set for c in sentence.lower(): if c.isalpha(): s.add(c) return len(s) == letters_count test('The quick, brown fox jumps over the lazy dog!', is_pangram('The quick, brown fox jumps over the lazy dog!'), True)
# 11211 / right_divisor (10) # _121_ # if next digit is zero? dont change number? but left divisor? number -= (left_divisor * left_digit) number /= right_divisor # we move left divisor by 20^2 as two digits moved left_divisor /= 100 #print "end number: %s" % number return True test("1009009001", is_palindrome_number(1009009001), True) test("1100011", is_palindrome_number(1100011), True) test("100", is_palindrome_number(100), False) test("1000", is_palindrome_number(1000), False) test("1000000", is_palindrome_number(1000000), False) test("1000001", is_palindrome_number(1000001), True) test("0", is_palindrome_number(0), True) test("121", is_palindrome_number(121), True) test("10", is_palindrome_number(10), False) test("11", is_palindrome_number(11), True) test("-121", is_palindrome_number(-121), False) test("1", is_palindrome_number(1), True) test("111999", is_palindrome_number(111999), False) test("111999111", is_palindrome_number(111999111), True) test("11199911", is_palindrome_number(11199911), False) test("1000021", is_palindrome_number(1000021), False)