Merge pull request #88 from TheAlgorithms/add-more-explanation-to-array-challenge

O(1) space approach - Get products of all other elements
This commit is contained in:
vzvu3k6k 2021-03-05 04:55:16 +09:00 committed by GitHub
commit 06ce984675
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 86 additions and 11 deletions

View file

@ -5,15 +5,25 @@
# each element at index `i` of the new array is the product of
# all the numbers in the original array except the one at `i`.
#
# This file solves the algorithm in 3 approaches:
#
# 1. Brute force
# 2. Left and Right product lists
# 3. O(1) space approach
#
#
# 1. Brute force solution
#
def calculate_products_of_all_other_elements(nums)
product_of_other_elements = Array.new(nums.length, 1)
product_of_other_elements = Array.new(nums.count, 1)
nums.each_with_index do |_num1, i|
nums.each_with_index do |num2, j|
product_of_other_elements[i] = product_of_other_elements[i] * num2 if i != j
nums.count.times do |i|
nums.count.times do |j|
next if i == j
product_of_other_elements[i] = product_of_other_elements[i] * nums[j]
end
end
@ -23,17 +33,27 @@ end
puts(calculate_products_of_all_other_elements([1, 2, 3]))
#
# 2. O(n) time and space
# Arrays - Get Products of all other elements in Ruby
# Approach 2: Left and Right product lists
#
# Complexity analysis
#
# Time complexity: O(N) where N represents the number of elements in the input
# array. We use one iteration to construct the array prefix_products, one to construct
# the array suffix_products and one last to construct the answeranswer array using L and R.
# Space complexity: O(N) used up by the two intermediate arrays that
# we constructed to keep track of product of elements to the left and right.
# Generates prefix products
# prefix_products[i] contains the product of all the elements to the left
# Note: for the element at index '0', there are no elements to the left,
# so the prefix_products[0] would be 1
def build_prefix_products(nums)
prefix_products = []
nums.each do |num|
prefix_products << if prefix_products.count > 0
(prefix_products.last * num)
prefix_products.last * num
else
num
end
@ -43,12 +63,15 @@ def build_prefix_products(nums)
end
# Generates suffix products
# suffix_products[i] contains the product of all the elements to the right
# Note: for the element at index 'length - 1', there are no elements to the right,
# so the suffix_products[length - 1] would be 1
def build_suffix_products(nums)
suffix_products = []
nums.reverse.each do |num|
suffix_products << if suffix_products.count > 0
(suffix_products.last * num)
suffix_products.last * num
else
num
end
@ -58,13 +81,16 @@ def build_suffix_products(nums)
end
# Builds output
# For the first element, suffix_products[i] would be product except self
# For the last element of the array, product except self would be prefix_products[i]
# Else, multiple product of all elements to the left and to the right
def output(prefix_products, suffix_products, nums)
result = []
nums.reverse.each_with_index do |_num, index|
nums.count.times do |index|
result << if index == 0
suffix_products[index + 1]
elsif index == nums.length - 1
elsif index == nums.count - 1
prefix_products[index - 1]
else
(prefix_products[index - 1] * suffix_products[index + 1])
@ -85,3 +111,53 @@ end
puts(products([1, 2, 3]))
# => [6, 3, 2]
#
# Approach 3: O(1) space approach
#
# This approach is essentially an extension of the approach 2.
# Basically, we will be using the output array as one of L or R and we will
# be constructing the other one on the fly.
# Complexity analysis
#
# Time complexity: O(N) where N represents the number of elements in the input
# array. We use one iteration to construct the array L, one to update the array
# answer.
# Space complexity: O(1) since don't use any additional array for our
# computations. The problem statement mentions that using the answer
# array doesn't add to the space complexity.
def products(nums)
return [] if nums.count < 2
res = [1]
# res[i] contains the product of all the elements to the left
# Note: for the element at index '0', there are no elements to the left,
# so the res[0] would be 1
(0..(nums.count - 2)).each do |i|
num = nums[i]
res << num * res[i]
end
# product contains the product of all the elements to the right
# Note: for the element at index 'length - 1', there are no elements to the right,
# so the product would be 1
product = 1
(nums.count - 1).downto(1) do |i|
num = nums[i]
# For the index 'i', product would contain the
# product of all elements to the right. We update product accordingly.
res[i - 1] *= (product * num)
product *= num
end
res
end
puts(products([1, 2, 3]))
# => [6, 3, 2]

View file

@ -146,7 +146,6 @@ class DoublyLinkedList
print "#{head.val} --> "
if head.next.nil?
puts("nil\n")
return
else
print_values(head.next)
end