#!/usr/bin/env python # coding: utf-8 # This notebook was prepared by [Donne Martin](https://github.com/donnemartin). Source and license info is on [GitHub](https://github.com/donnemartin/interactive-coding-challenges). # # Solution Notebook # ## Problem: Given a list of ints, find the products of every other int for each index. # # * [Constraints](#Constraints) # * [Test Cases](#Test-Cases) # * [Algorithm](#Algorithm) # * [Code](#Code) # * [Unit Test](#Unit-Test) # ## Constraints # # * Can we use division? # * No # * Is the output a list of ints? # * Yes # * Can we assume the inputs are valid? # * No # * Can we assume this fits memory? # * Yes # ## Test Cases # #
# * None -> TypeError
# * [] -> []
# * [0] -> []
# * [0, 1] -> [1, 0]
# * [0, 1, 2] -> [2, 0, 0]
# * [1, 2, 3, 4] -> [24, 12, 8, 6]
# 
# ## Algorithm # # ### Brute force: # #
# sum = 1
#  |
# [1, 2, 3, 4]
#  ^
# skip if both pointers are pointing to the same spot
#     |
# [1, 2, 3, 4]
#  ^
# sum *= 2
#        |
# [1, 2, 3, 4]
#  ^
# sum *= 3
#           |
# [1, 2, 3, 4]
#  ^
# sum *= 4
# results.append(sum)
# results = [24]
# 
# repeat for every element in the input list to obtain:
# 
# [24, 12, 8, 6]
#  
# 
# # Complexity: # * Time: O(n^2) # * Space: O(n) # # ### Greedy # #
# input  = [1, 2, 3, 4]
# result = [2*3*4, 1*3*4, 1*2*4, 1*2*3]
# 
# Note we are duplicating multiplications with the brute force approach.
# 
# We'll calculate all products before an index, and all products after an index.
# We'll then multiple these two together to form the result.
# 
# input  = [1,         2,     3,     4]
# before = [1,         1,   1*2, 1*2*3]
# after  = [2*3*4, 1*3*4, 1*2*4,     1]
# result = [   24,    12,     8,     6] 
# 
# # Complexity: # * Time: O(n) # * Space: O(n) # ## Code # In[1]: class Solution(object): def mult_other_numbers_brute(self, array): if array is None: raise TypeError('array cannot be None') if not array: return array if len(array) == 1: return [] result = [] for i in range(len(array)): curr_sum = 1 for j in range(len(array)): if i == j: continue curr_sum *= array[j] result.append(curr_sum) return result def mult_other_numbers(self, array): if array is None: raise TypeError('array cannot be None') if not array: return array if len(array) == 1: return [] result = [None] * len(array) curr_product = 1 for i in range(len(array)): result[i] = curr_product curr_product *= array[i] curr_product = 1 for i in range(len(array))[::-1]: result[i] *= curr_product curr_product *= array[i] return result # ## Unit Test # In[2]: get_ipython().run_cell_magic('writefile', 'test_mult_other_numbers.py', "import unittest\n\n\nclass TestMultOtherNumbers(unittest.TestCase):\n\n def test_mult_other_numbers(self):\n solution = Solution()\n self.assertRaises(TypeError, solution.mult_other_numbers, None)\n self.assertEqual(solution.mult_other_numbers([0]), [])\n self.assertEqual(solution.mult_other_numbers([0, 1]), [1, 0])\n self.assertEqual(solution.mult_other_numbers([0, 1, 2]), [2, 0, 0])\n self.assertEqual(solution.mult_other_numbers([1, 2, 3, 4]), [24, 12, 8, 6])\n print('Success: test_mult_other_numbers')\n\n\ndef main():\n test = TestMultOtherNumbers()\n test.test_mult_other_numbers()\n\n\nif __name__ == '__main__':\n main()\n") # In[3]: get_ipython().run_line_magic('run', '-i test_mult_other_numbers.py')