diff --git a/data_structures/arrays/sort_squares_of_an_array.rb b/data_structures/arrays/sort_squares_of_an_array.rb index 820f6e6..717fdb3 100644 --- a/data_structures/arrays/sort_squares_of_an_array.rb +++ b/data_structures/arrays/sort_squares_of_an_array.rb @@ -22,6 +22,7 @@ print(sorted_squares([4, -1, -9, 2])) def bubble_sort(array) array_length = array.size return array if array_length <= 1 + loop do swapped = false (array_length - 1).times do |i| diff --git a/data_structures/arrays/two_sum.rb b/data_structures/arrays/two_sum.rb index 318ee7f..e0beb08 100644 --- a/data_structures/arrays/two_sum.rb +++ b/data_structures/arrays/two_sum.rb @@ -1,4 +1,5 @@ # Challenge name: Two Sum +# # Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target. # # You may assume that each input would have exactly one solution, and you may not use the same element twice. @@ -23,44 +24,52 @@ # @param {Integer} target # @return {Integer[]} -# +# # Approach 1: Brute Force with Addition # + +# Complexity analysis + # Time Complexity: O(n^2). For each element, we try to find its complement # by looping through the rest of the array which takes O(n) time. # Therefore, the time complexity is O(n^2) + # Space complexity: O(1) -# + def two_sum(nums, target) result_array = [] - nums.each_with_index do |num, i| - nums.each_with_index do |num, j| - if i != j && i < j - current_sum = nums[i] + nums[j] - if current_sum == target - return [i, j] - end - end + nums.count.times do |i| + nums.count.times do |j| + next unless i != j && i < j + + current_sum = nums[i] + nums[j] + + return [i, j] if current_sum == target end end end -print two_sum([2, 7, 11, 15], 9) +print(two_sum([2, 7, 11, 15], 9)) # => [0,1] -print two_sum([3, 2, 4], 6) + +print(two_sum([3, 2, 4], 6)) # => [1,2] -print two_sum([3, 3], 6) + +print(two_sum([3, 3], 6)) # => [0,1] # # Approach 2: Brute Force with Difference # +# Complexity analysis +# # Time Complexity: O(N^2), where N is the length of the array # def two_sum(nums, target) - nums.each_with_index do |num, i| + nums.count.times do |i| target_difference = target - nums[i] + nums.each_with_index do |num, j| if i != j && num == target_difference return [i, j] @@ -69,38 +78,102 @@ def two_sum(nums, target) end end -print two_sum([2, 7, 11, 15], 9) +print(two_sum([2, 7, 11, 15], 9)) # => [0,1] -print two_sum([3, 2, 4], 6) + +print(two_sum([3, 2, 4], 6)) # => [1,2] -print two_sum([3, 3], 6) + +print(two_sum([3, 3], 6)) # => [0,1] # # Approach 3: Using a Hash # + +# Complexity analysis + # Time complexity: O(n). We traverse the list containing n elements exactly twice. # Since the hash table reduces the lookup time to O(1), the time complexity is O(n). # Space complexity: O(n). The extra space required depends on the number of items # stored in the hash table, which stores exactly n elements. -# + def two_sum(nums, target) hash = {} + # create a hash to store values and their indices nums.each_with_index do |num, i| hash[num] = i end + # iterate over nums array to find the target (difference between sum target and num) nums.each_with_index do |num, i| difference_target = target - num - return [i, hash[difference_target]] if hash[difference_target] && hash[difference_target] != i + + if hash[difference_target] && hash[difference_target] != i + return [i, hash[difference_target]] + end end end -print two_sum([2, 7, 11, 15], 9) +nums = [2, 7, 11, 15] +target = 9 +print(two_sum(nums, target)) # => [0,1] -print two_sum([3, 2, 4], 6) + +nums = [3, 2, 4] +target = 6 +print(two_sum(nums, target)) # => [1,2] -print two_sum([3, 3], 6) + +nums = [3, 3] +target = 6 +print(two_sum(nums, target)) +# => [0,1] + +# +# Approach 4: Two pointers +# + +# Complexity analysis + +# Time complexity: O(n). Each of the n elements is visited at +# most once, thus the time complexity is O(n). + +# Space complexity: O(1). We only use two indexes, the space +# complexity is O(1). + +def two_sum(numbers, target) + i = 0 + j = numbers.length - 1 + # note: sorting the array is important + numbers = numbers.sort + + while i < j + sum = numbers[i] + numbers[j] + + if target < sum + j -= 1 + elsif target > sum + i += 1 + else + return [i, j] + end + end +end + +nums = [2, 7, 11, 15] +target = 9 +print(two_sum(nums, target)) +# => [0,1] + +nums = [2, 3, 4] +target = 6 +print(two_sum(nums, target)) +# => [0,2] + +nums = [-1, 0] +target = -1 +print(two_sum(nums, target)) # => [0,1]