mirror of
https://github.com/TheAlgorithms/Ruby
synced 2025-01-13 08:01:03 +01:00
Merge branch 'master' into master
This commit is contained in:
commit
d3d66e1ef1
28 changed files with 1321 additions and 99 deletions
45
DIRECTORY.md
45
DIRECTORY.md
|
@ -1,10 +1,16 @@
|
|||
|
||||
## Backtracking
|
||||
* [Generate Paranthesis](https://github.com/TheAlgorithms/Ruby/blob/master/backtracking/generate_paranthesis.rb)
|
||||
|
||||
## Bit Manipulation
|
||||
* [Power Of Two](https://github.com/TheAlgorithms/Ruby/blob/master/bit_manipulation/power_of_two.rb)
|
||||
|
||||
## Ciphers
|
||||
* [Merkle Hellman Cryptosystem](https://github.com/TheAlgorithms/Ruby/blob/master/ciphers/merkle_hellman_cryptosystem.rb)
|
||||
|
||||
## Conversions
|
||||
* [Temperature Conversions](https://github.com/TheAlgorithms/Ruby/blob/master/conversions/temperature_conversions.rb)
|
||||
|
||||
## Data Structures
|
||||
* Arrays
|
||||
* [Add Digits](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/add_digits.rb)
|
||||
|
@ -12,10 +18,19 @@
|
|||
* [Find The Highest Altitude](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/find_the_highest_altitude.rb)
|
||||
* [Fizz Buzz](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/fizz_buzz.rb)
|
||||
* [Get Products Of All Other Elements](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/get_products_of_all_other_elements.rb)
|
||||
* [Jewels And Stones](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/jewels_and_stones.rb)
|
||||
* [Intersection](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/intersection.rb)
|
||||
* [Next Greater Element](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/next_greater_element.rb)
|
||||
* [Remove Elements](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/remove_elements.rb)
|
||||
* [Richest Customer Wealth](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/richest_customer_wealth.rb)
|
||||
* [Shuffle Array](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/shuffle_array.rb)
|
||||
* [Single Number](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/single_number.rb)
|
||||
* [Sort Squares Of An Array](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/sort_squares_of_an_array.rb)
|
||||
* [Sorted Arrays Intersection](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/sorted_arrays_intersection.rb)
|
||||
* Strings
|
||||
* [Anagram Checker](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/strings/anagram_checker.rb)
|
||||
* [Jewels And Stones](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/strings/jewels_and_stones.rb)
|
||||
* [Palindrome](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/strings/palindrome.rb)
|
||||
* [Remove Vowels](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/strings/remove_vowels.rb)
|
||||
* [Two Sum](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/two_sum.rb)
|
||||
* [Two Sum Ii](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/arrays/two_sum_ii.rb)
|
||||
* Binary Trees
|
||||
|
@ -23,6 +38,12 @@
|
|||
* [Invert](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/binary_trees/invert.rb)
|
||||
* [Postorder Traversal](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/binary_trees/postorder_traversal.rb)
|
||||
* [Preorder Traversal](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/binary_trees/preorder_traversal.rb)
|
||||
* Hash Table
|
||||
* [Anagram Checker](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/hash_table/anagram_checker.rb)
|
||||
* [Arrays Intersection](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/hash_table/arrays_intersection.rb)
|
||||
* [Find All Duplicates In An Array](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/hash_table/find_all_duplicates_in_an_array.rb)
|
||||
* [Richest Customer Wealth](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/hash_table/richest_customer_wealth.rb)
|
||||
* [Two Sum](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/hash_table/two_sum.rb)
|
||||
* Linked Lists
|
||||
* [Circular Linked List](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/linked_lists/circular_linked_list.rb)
|
||||
* [Doubly Linked List](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/linked_lists/doubly_linked_list.rb)
|
||||
|
@ -46,19 +67,24 @@
|
|||
## Maths
|
||||
* [Abs](https://github.com/TheAlgorithms/Ruby/blob/master/maths/abs.rb)
|
||||
* [Abs Test](https://github.com/TheAlgorithms/Ruby/blob/master/maths/abs_test.rb)
|
||||
* [Add](https://github.com/TheAlgorithms/Ruby/blob/master/maths/add.rb)
|
||||
* [Add Digits](https://github.com/TheAlgorithms/Ruby/blob/master/maths/add_digits.rb)
|
||||
* [Aliquot Sum](https://github.com/TheAlgorithms/Ruby/blob/master/maths/aliquot_sum.rb)
|
||||
* [Aliquot Sum Test](https://github.com/TheAlgorithms/Ruby/blob/master/maths/aliquot_sum_test.rb)
|
||||
* [Average Mean](https://github.com/TheAlgorithms/Ruby/blob/master/maths/average_mean.rb)
|
||||
* [Average Median](https://github.com/TheAlgorithms/Ruby/blob/master/maths/average_median.rb)
|
||||
* [Binary To Decimal](https://github.com/TheAlgorithms/Ruby/blob/master/maths/binary_to_decimal.rb)
|
||||
* [Ceil](https://github.com/TheAlgorithms/Ruby/blob/master/maths/ceil.rb)
|
||||
* [Ceil Test](https://github.com/TheAlgorithms/Ruby/blob/master/maths/ceil_test.rb)
|
||||
* [Decimal To Binary](https://github.com/TheAlgorithms/Ruby/blob/master/maths/decimal_to_binary.rb)
|
||||
* [Factorial](https://github.com/TheAlgorithms/Ruby/blob/master/maths/factorial.rb)
|
||||
* [Factorial Non-recursive and Non-iterative](https://github.com/TheAlgorithms/Ruby/blob/master/maths/factorial_non_recursive_non_iterative.rb)
|
||||
* [Fibonacci](https://github.com/TheAlgorithms/Ruby/blob/master/maths/fibonacci.rb)
|
||||
* [Find Max](https://github.com/TheAlgorithms/Ruby/blob/master/maths/find_max.rb)
|
||||
* [Find Min](https://github.com/TheAlgorithms/Ruby/blob/master/maths/find_min.rb)
|
||||
* [Number Of Digits](https://github.com/TheAlgorithms/Ruby/blob/master/maths/number_of_digits.rb)
|
||||
* [Power Of Two](https://github.com/TheAlgorithms/Ruby/blob/master/maths/power_of_two.rb)
|
||||
* [Prime Number](https://github.com/TheAlgorithms/Ruby/blob/master/maths/prime_number.rb)
|
||||
* [Square Root](https://github.com/TheAlgorithms/Ruby/blob/master/maths/square_root.rb)
|
||||
* [Square Root Test](https://github.com/TheAlgorithms/Ruby/blob/master/maths/square_root_test.rb)
|
||||
* [Sum Of Digits](https://github.com/TheAlgorithms/Ruby/blob/master/maths/sum_of_digits.rb)
|
||||
|
@ -87,14 +113,14 @@
|
|||
* [Sol1](https://github.com/TheAlgorithms/Ruby/blob/master/project_euler/problem_5/sol1.rb)
|
||||
|
||||
## Searches
|
||||
* [Binary Search](https://github.com/TheAlgorithms/Ruby/blob/master/Searches/binary_search.rb)
|
||||
* [Depth First Search](https://github.com/TheAlgorithms/Ruby/blob/master/Searches/depth_first_search.rb)
|
||||
* [Double Linear Search](https://github.com/TheAlgorithms/Ruby/blob/master/Searches/double_linear_search.rb)
|
||||
* [Jump Search](https://github.com/TheAlgorithms/Ruby/blob/master/Searches/jump_search.rb)
|
||||
* [Linear Search](https://github.com/TheAlgorithms/Ruby/blob/master/Searches/linear_search.rb)
|
||||
* [Recursive Double Linear Search](https://github.com/TheAlgorithms/Ruby/blob/master/Searches/recursive_double_linear_search.rb)
|
||||
* [Recursive Linear Search](https://github.com/TheAlgorithms/Ruby/blob/master/Searches/recursive_linear_search.rb)
|
||||
* [Ternary Search](https://github.com/TheAlgorithms/Ruby/blob/master/Searches/ternary_search.rb)
|
||||
* [Binary Search](https://github.com/TheAlgorithms/Ruby/blob/master/searches/binary_search.rb)
|
||||
* [Depth First Search](https://github.com/TheAlgorithms/Ruby/blob/master/searches/depth_first_search.rb)
|
||||
* [Double Linear Search](https://github.com/TheAlgorithms/Ruby/blob/master/searches/double_linear_search.rb)
|
||||
* [Jump Search](https://github.com/TheAlgorithms/Ruby/blob/master/searches/jump_search.rb)
|
||||
* [Linear Search](https://github.com/TheAlgorithms/Ruby/blob/master/searches/linear_search.rb)
|
||||
* [Recursive Double Linear Search](https://github.com/TheAlgorithms/Ruby/blob/master/searches/recursive_double_linear_search.rb)
|
||||
* [Recursive Linear Search](https://github.com/TheAlgorithms/Ruby/blob/master/searches/recursive_linear_search.rb)
|
||||
* [Ternary Search](https://github.com/TheAlgorithms/Ruby/blob/master/searches/ternary_search.rb)
|
||||
|
||||
## Sorting
|
||||
* [Bogo Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/bogo_sort.rb)
|
||||
|
@ -117,4 +143,5 @@
|
|||
* [Selection Sort Test](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/selection_sort_test.rb)
|
||||
* [Shell Sort](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/shell_sort.rb)
|
||||
* [Shell Sort Test](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/shell_sort_test.rb)
|
||||
* [Sort Color](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/sort_color.rb)
|
||||
* [Sort Tests](https://github.com/TheAlgorithms/Ruby/blob/master/sorting/sort_tests.rb)
|
||||
|
|
106
backtracking/generate_paranthesis.rb
Normal file
106
backtracking/generate_paranthesis.rb
Normal file
|
@ -0,0 +1,106 @@
|
|||
# Given n pairs of parentheses, write a function to generate all combinations
|
||||
# of well-formed parentheses.
|
||||
#
|
||||
# Example 1:
|
||||
#
|
||||
# Input: n = 3
|
||||
# Output: ["((()))","(()())","(())()","()(())","()()()"]
|
||||
# Example 2:
|
||||
#
|
||||
# Input: n = 1
|
||||
# Output: ["()"]
|
||||
#
|
||||
#
|
||||
# Constraints:
|
||||
#
|
||||
# 1 <= n <= 8
|
||||
|
||||
# Approach:
|
||||
#
|
||||
# Let's only add '(' or ')' when we know it will remain a valid sequence.
|
||||
# We can do this by keeping track of the number of opening and closing brackets
|
||||
# we have placed so far.
|
||||
#
|
||||
# We can start an opening bracket if we still have one (of n) left to place.
|
||||
# And we could start a closing bracket if it'd not exceed the number of opening
|
||||
# brackets.
|
||||
|
||||
# Complexity Analysis
|
||||
#
|
||||
# Time Complexity: O(4^n/sqrt(n)). Each valid sequence has at most n steps during the backtracking procedure.
|
||||
# Space Complexity: O(4^n/sqrt(n)), as described above, and using O(n) space to store the sequence.
|
||||
|
||||
# Refer to the attached diagram for recursion,
|
||||
# The numbers next to each node are the counts of left and right parantheses
|
||||
|
||||
# @param {Integer} n
|
||||
# @return {String[]}
|
||||
def generate_parenthesis(n)
|
||||
parenthesis = []
|
||||
backtrack(parenthesis, "", 0, 0, n)
|
||||
parenthesis
|
||||
end
|
||||
|
||||
def backtrack(parenthesis, curr, open, close, max)
|
||||
if curr.length == max * 2
|
||||
parenthesis.push(curr)
|
||||
return
|
||||
end
|
||||
|
||||
if open < max
|
||||
backtrack(parenthesis, curr + "(", open + 1, close, max)
|
||||
end
|
||||
|
||||
if close < open
|
||||
backtrack(parenthesis, curr + ")", open, close + 1, max)
|
||||
end
|
||||
end
|
||||
|
||||
n = 3
|
||||
print(generate_parenthesis(n))
|
||||
# Output: ["((()))","(()())","(())()","()(())","()()()"]
|
||||
|
||||
# *** Example: n = 3 *** Space after each DFS instance
|
||||
# backtrack called with 0 0 []
|
||||
# backtrack called with ( 1 0 []
|
||||
# backtrack called with (( 2 0 []
|
||||
# backtrack called with ((( 3 0 []
|
||||
# backtrack called with ((() 3 1 []
|
||||
# backtrack called with ((()) 3 2 []
|
||||
# backtrack called with ((())) 3 3 []
|
||||
# backtrack return with ((()) 3 2 ["((()))"]
|
||||
# backtrack return with ((() 3 1 ["((()))"]
|
||||
# backtrack return with ((( 3 0 ["((()))"]
|
||||
# backtrack called with (() 2 1 ["((()))"]
|
||||
# backtrack called with (()( 3 1 ["((()))"]
|
||||
# backtrack called with (()() 3 2 ["((()))"]
|
||||
# backtrack called with (()()) 3 3 ["((()))"]
|
||||
# backtrack return with (()() 3 2 ["((()))", "(()())"]
|
||||
# backtrack return with (()( 3 1 ["((()))", "(()())"]
|
||||
# backtrack called with (()) 2 2 ["((()))", "(()())"]
|
||||
# backtrack called with (())( 3 2 ["((()))", "(()())"]
|
||||
# backtrack called with (())() 3 3 ["((()))", "(()())"]
|
||||
# backtrack return with (())( 3 2 ["((()))", "(()())", "(())()"]
|
||||
# backtrack return with (()) 2 2 ["((()))", "(()())", "(())()"]
|
||||
# backtrack return with (() 2 1 ["((()))", "(()())", "(())()"]
|
||||
# backtrack return with (( 2 0 ["((()))", "(()())", "(())()"]
|
||||
# backtrack called with () 1 1 ["((()))", "(()())", "(())()"]
|
||||
# backtrack called with ()( 2 1 ["((()))", "(()())", "(())()"]
|
||||
# backtrack called with ()(( 3 1 ["((()))", "(()())", "(())()"]
|
||||
# backtrack called with ()(() 3 2 ["((()))", "(()())", "(())()"]
|
||||
# backtrack called with ()(()) 3 3 ["((()))", "(()())", "(())()"]
|
||||
# backtrack return with ()(() 3 2 ["((()))", "(()())", "(())()", "()(())"]
|
||||
# backtrack return with ()(( 3 1 ["((()))", "(()())", "(())()", "()(())"]
|
||||
# backtrack called with ()() 2 2 ["((()))", "(()())", "(())()", "()(())"]
|
||||
# backtrack called with ()()( 3 2 ["((()))", "(()())", "(())()", "()(())"]
|
||||
# backtrack called with ()()() 3 3 ["((()))", "(()())", "(())()", "()(())"]
|
||||
# backtrack return with ()()( 3 2 ["((()))", "(()())", "(())()", "()(())", "()()()"]
|
||||
# backtrack return with ()() 2 2 ["((()))", "(()())", "(())()", "()(())", "()()()"]
|
||||
# backtrack return with ()( 2 1 ["((()))", "(()())", "(())()", "()(())", "()()()"]
|
||||
# backtrack return with () 1 1 ["((()))", "(()())", "(())()", "()(())", "()()()"]
|
||||
# backtrack return with ( 1 0 ["((()))", "(()())", "(())()", "()(())", "()()()"]
|
||||
# backtrack return with 0 0 ["((()))", "(()())", "(())()", "()(())", "()()()"]
|
||||
|
||||
n = 1
|
||||
print(generate_parenthesis(n))
|
||||
# Output: ["()"]
|
|
@ -87,44 +87,3 @@ Benchmark.bmbm do |x|
|
|||
print(find_duplicates(long_array))
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Approach 3: Hash map
|
||||
#
|
||||
|
||||
#
|
||||
# Complexity Analysis
|
||||
#
|
||||
# Time complexity: O(n) average case.
|
||||
#
|
||||
|
||||
def find_duplicates(array)
|
||||
result_hash = {}
|
||||
result_array = []
|
||||
|
||||
# loop through array and build a hash with counters
|
||||
# where the key is the array element and the counter is the value
|
||||
# increase counter when duplicate is found
|
||||
array.each do |num|
|
||||
if result_hash[num].nil?
|
||||
result_hash[num] = 1
|
||||
else
|
||||
result_hash[num] += 1
|
||||
end
|
||||
end
|
||||
|
||||
# loop through hash and look for values > 1
|
||||
result_hash.each do |k, v|
|
||||
result_array.push(k) if v > 1
|
||||
end
|
||||
|
||||
# return keys
|
||||
result_array
|
||||
end
|
||||
|
||||
Benchmark.bmbm do |x|
|
||||
x.report('execute algorithm 3') do
|
||||
print(find_duplicates(array))
|
||||
print(find_duplicates(long_array))
|
||||
end
|
||||
end
|
||||
|
|
125
data_structures/arrays/intersection.rb
Normal file
125
data_structures/arrays/intersection.rb
Normal file
|
@ -0,0 +1,125 @@
|
|||
# Challenge name: Intersection of two arrays ii
|
||||
#
|
||||
# Given two arrays, write a function to compute their intersection.
|
||||
#
|
||||
# @param {Integer[]} nums1
|
||||
# @param {Integer[]} nums2
|
||||
# @return {Integer[]}
|
||||
|
||||
#
|
||||
# Approach 1: Brute Force
|
||||
#
|
||||
# Time Complexity: O(n^2)
|
||||
#
|
||||
def intersect(arr1, arr2)
|
||||
result = []
|
||||
|
||||
if arr1.length < arr2.length
|
||||
shorter = arr1
|
||||
longer = arr2
|
||||
else
|
||||
shorter = arr2
|
||||
longer = arr1
|
||||
end
|
||||
|
||||
shorter.each do |matcher|
|
||||
longer.each do |number|
|
||||
next if number != matcher
|
||||
result.push(number)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
nums1 = [1, 2, 2, 1]
|
||||
nums2 = [2, 2]
|
||||
puts intersect(nums1, nums2)
|
||||
# => [2,2]
|
||||
|
||||
nums1 = [4, 9, 5]
|
||||
nums2 = [9, 4, 9, 8, 4]
|
||||
puts intersect(nums1, nums2)
|
||||
# => [4,9]
|
||||
|
||||
#
|
||||
# Approach 2: Hash
|
||||
#
|
||||
# Complexity Analysis
|
||||
#
|
||||
# Time Complexity: O(n+m), where n and m are the lengths of the arrays.
|
||||
# We iterate through the first, and then through the second array; insert
|
||||
# and lookup operations in the hash map take a constant time.
|
||||
#
|
||||
# Space Complexity: O(min(n,m)). We use hash map to store numbers (and their
|
||||
# counts) from the smaller array.
|
||||
#
|
||||
def intersect(arr1, arr2)
|
||||
result = []
|
||||
|
||||
hash = Hash.new(0)
|
||||
|
||||
arr2.each {|num| hash[num] += 1 }
|
||||
|
||||
arr1.each do |num|
|
||||
if hash.has_key?(num)
|
||||
result << num if hash[num] >= 1
|
||||
hash[num] -= 1
|
||||
end
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
nums1 = [1, 2, 2, 1]
|
||||
nums2 = [2, 2]
|
||||
puts intersect(nums1, nums2)
|
||||
# => [2,2]
|
||||
|
||||
nums1 = [4, 9, 5]
|
||||
nums2 = [9, 4, 9, 8, 4]
|
||||
puts intersect(nums1, nums2)
|
||||
# => [4,9]
|
||||
|
||||
#
|
||||
# Approach 3: Two Pointers
|
||||
#
|
||||
# Complexity analysis:
|
||||
|
||||
# Time Complexity: O(nlogn + mlogm), where n and m are the lengths of the arrays. We sort two arrays independently and then do a linear scan.
|
||||
# Space Complexity: from O(logn+logm) to O(n+m), depending on the implementation of the sorting algorithm.
|
||||
#
|
||||
def intersect(nums1, nums2)
|
||||
result = []
|
||||
p1 = 0
|
||||
p2 = 0
|
||||
nums1 = nums1.sort
|
||||
nums2 = nums2.sort
|
||||
while p1 < nums1.length && p2 < nums2.length
|
||||
if nums1[p1] < nums2[p2]
|
||||
p1 += 1
|
||||
elsif nums1[p1] > nums2[p2]
|
||||
p2 += 1
|
||||
elsif nums1[p1] == nums2[p2]
|
||||
result << nums1[p1]
|
||||
p1 += 1
|
||||
p2 += 1
|
||||
end
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
nums1 = [1, 2, 2, 1]
|
||||
nums2 = [2, 2]
|
||||
intersect(nums1, nums2)
|
||||
|
||||
nums1 = [1, 2, 2, 1]
|
||||
nums2 = [2, 2]
|
||||
puts intersect(nums1, nums2)
|
||||
# => [2,2]
|
||||
|
||||
nums1 = [4, 9, 5]
|
||||
nums2 = [9, 4, 9, 8, 4]
|
||||
puts intersect(nums1, nums2)
|
||||
# => [4,9]
|
64
data_structures/arrays/next_greater_element.rb
Normal file
64
data_structures/arrays/next_greater_element.rb
Normal file
|
@ -0,0 +1,64 @@
|
|||
# You are given two integer arrays nums1 and nums2 both of unique elements, where nums1 is a subset of nums2.
|
||||
#
|
||||
# Find all the next greater numbers for nums1's elements in the corresponding places of nums2.
|
||||
#
|
||||
# The Next Greater Number of a number x in nums1 is the first greater number to its right in nums2. If it does not exist, return -1 for this number.
|
||||
|
||||
# Example 1:
|
||||
#
|
||||
# Input: nums1 = [4,1,2], nums2 = [1,3,4,2]
|
||||
# Output: [-1,3,-1]
|
||||
#
|
||||
# Explanation:
|
||||
# For number 4 in the first array, you cannot find the next greater number for it in the second array, so output -1.
|
||||
# For number 1 in the first array, the next greater number for it in the second array is 3.
|
||||
# For number 2 in the first array, there is no next greater number for it in the second array, so output -1.
|
||||
#
|
||||
# Example 2:
|
||||
#
|
||||
# Input: nums1 = [2,4], nums2 = [1,2,3,4]
|
||||
# Output: [3,-1]
|
||||
#
|
||||
# Explanation:
|
||||
# For number 2 in the first array, the next greater number for it in the second array is 3.
|
||||
# For number 4 in the first array, there is no next greater number for it in the second array, so output -1.
|
||||
|
||||
#
|
||||
# Approach: Brute Force
|
||||
#
|
||||
|
||||
# Complexity Analysis
|
||||
#
|
||||
# Time complexity: O(m*n). The complete nums1 array (of size n) needs to be scanned for all the m elements of nums2 in the worst case.
|
||||
# Space complexity: O(1). No additional space since we're swapping elements in nums1 and returning the input array.
|
||||
|
||||
# @param {Integer[]} nums1
|
||||
# @param {Integer[]} nums2
|
||||
# @return {Integer[]}
|
||||
def next_greater_element(nums1, nums2)
|
||||
nums1.each_with_index do |nums1_value, pointer1|
|
||||
max = 0
|
||||
pos_nums2 = nums2.find_index(nums1_value)
|
||||
|
||||
nums2[pos_nums2..nums2.count].each do |nums2_value|
|
||||
if nums2_value > nums1_value
|
||||
max = nums2_value
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
nums1[pointer1] = (nums1_value < max ? max : -1)
|
||||
end
|
||||
|
||||
nums1
|
||||
end
|
||||
|
||||
nums1 = [4, 1, 2]
|
||||
nums2 = [1, 3, 4, 2]
|
||||
print next_greater_element(nums1, nums2)
|
||||
# Output: [-1,3,-1]
|
||||
|
||||
nums1 = [2, 4]
|
||||
nums2 = [1, 2, 3, 4]
|
||||
print next_greater_element(nums1, nums2)
|
||||
# Output: [3,-1]
|
56
data_structures/arrays/richest_customer_wealth.rb
Normal file
56
data_structures/arrays/richest_customer_wealth.rb
Normal file
|
@ -0,0 +1,56 @@
|
|||
# Challenge name: Richest Customer Wealth
|
||||
#
|
||||
# You are given an m x n integer grid accounts where accounts[i][j]
|
||||
# is the amount of money the ith customer has in the jth bank.
|
||||
#
|
||||
# Return the wealth that the richest customer has.
|
||||
# A customer's wealth is the amount of money they have in all
|
||||
# their bank accounts. The richest customer is the customer that
|
||||
# has the maximum wealth.
|
||||
#
|
||||
# Example 1:
|
||||
# Input: accounts = [[1,2,3],[3,2,1]]
|
||||
# Output: 6
|
||||
# Explanation:
|
||||
# 1st customer has wealth = 1 + 2 + 3 = 6
|
||||
# 2nd customer has wealth = 3 + 2 + 1 = 6
|
||||
# Both customers are considered the richest with a wealth of 6
|
||||
# each, so return 6.
|
||||
#
|
||||
# Example 2:
|
||||
# Input: accounts = [[1,5],[7,3],[3,5]]
|
||||
# Output: 10
|
||||
# Explanation:
|
||||
# 1st customer has wealth = 6
|
||||
# 2nd customer has wealth = 10
|
||||
# 3rd customer has wealth = 8
|
||||
# The 2nd customer is the richest with a wealth of 10.
|
||||
#
|
||||
# Example 3:
|
||||
# Input: accounts = [[2,8,7],[7,1,3],[1,9,5]]
|
||||
# Output: 17
|
||||
|
||||
#
|
||||
# Approach: Brute Force
|
||||
#
|
||||
# Time Complexity: O(n)
|
||||
#
|
||||
def find_richest_customer_wealth(accounts)
|
||||
summed_accounts = []
|
||||
accounts.each do |customer|
|
||||
summed = 0
|
||||
customer.each do |account|
|
||||
summed += account
|
||||
end
|
||||
summed_accounts.push(summed)
|
||||
end
|
||||
|
||||
summed_accounts.sort.pop()
|
||||
end
|
||||
|
||||
puts find_richest_customer_wealth([[1,2,3],[3,2,1]])
|
||||
# => 6
|
||||
puts find_richest_customer_wealth([[1,5],[7,3],[3,5]])
|
||||
# => 10
|
||||
puts find_richest_customer_wealth([[2,8,7],[7,1,3],[1,9,5]])
|
||||
# => 17
|
109
data_structures/arrays/shuffle_array.rb
Normal file
109
data_structures/arrays/shuffle_array.rb
Normal file
|
@ -0,0 +1,109 @@
|
|||
# Challenge name: Shuffle the array
|
||||
#
|
||||
# Given the array nums consisting of 2n elements
|
||||
# in the form [x1,x2,...,xn,y1,y2,...,yn].
|
||||
# Return the array in the form [x1,y1,x2,y2,...,xn,yn].
|
||||
#
|
||||
# Example 1:
|
||||
# Input: nums = [2,5,1,3,4,7], n = 3
|
||||
# Output: [2,3,5,4,1,7]
|
||||
# Explanation: Since x1=2, x2=5, x3=1, y1=3, y2=4, y3=7 then the answer is [2,3,5,4,1,7].
|
||||
#
|
||||
# Example 2:
|
||||
# Input: nums = [1,2,3,4,4,3,2,1], n = 4
|
||||
# Output: [1,4,2,3,3,2,4,1]
|
||||
#
|
||||
# Example 3:
|
||||
# Input: nums = [1,1,2,2], n = 2
|
||||
# Output: [1,2,1,2]
|
||||
#
|
||||
# @param {Integer[]} nums
|
||||
# @param {Integer} n
|
||||
# @return {Integer[]}
|
||||
|
||||
#
|
||||
# Approach 1: New Array
|
||||
#
|
||||
# Time Complexity: O(N)
|
||||
#
|
||||
def shuffle(nums, n)
|
||||
result = []
|
||||
(0..n-1).count do |i|
|
||||
result.push(nums[i], nums[i+n])
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
nums = [2, 5, 1, 3, 4, 7]
|
||||
n = 3
|
||||
print(shuffle(nums, n))
|
||||
# Output: [2,3,5,4,1,7]
|
||||
nums = [1, 2, 3, 4, 4, 3, 2, 1]
|
||||
n = 4
|
||||
print(shuffle(nums, n))
|
||||
# Output: [1,4,2,3,3,2,4,1]
|
||||
nums = [1, 1, 2, 2]
|
||||
n = 2
|
||||
print(shuffle(nums, n))
|
||||
# Output: [1,2,1,2]
|
||||
|
||||
#
|
||||
# Approach 2: Use Ruby methods .insert() and .delete_at()
|
||||
#
|
||||
# Time Complexity: O(N)
|
||||
#
|
||||
|
||||
def shuffle(nums, n)
|
||||
current_index = 1
|
||||
(0..n-1).each do |i|
|
||||
nums.insert(current_index, nums.delete_at(i + n))
|
||||
current_index += 2
|
||||
end
|
||||
nums
|
||||
end
|
||||
|
||||
nums = [2, 5, 1, 3, 4, 7]
|
||||
n = 3
|
||||
print(shuffle(nums, n))
|
||||
# Output: [2,3,5,4,1,7]
|
||||
nums = [1, 2, 3, 4, 4, 3, 2, 1]
|
||||
n = 4
|
||||
print(shuffle(nums, n))
|
||||
# Output: [1,4,2,3,3,2,4,1]
|
||||
nums = [1, 1, 2, 2]
|
||||
n = 2
|
||||
print(shuffle(nums, n))
|
||||
# Output: [1,2,1,2]
|
||||
|
||||
#
|
||||
# Approach 3: Two Pointers
|
||||
#
|
||||
# Time Complexity: O(N)
|
||||
#
|
||||
|
||||
def shuffle(nums, n)
|
||||
result = []
|
||||
p1 = 0
|
||||
p2 = n
|
||||
|
||||
while p1 < n
|
||||
result.push(nums[p1], nums[p2])
|
||||
p1 +=1
|
||||
p2 +=1
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
nums = [2, 5, 1, 3, 4, 7]
|
||||
n = 3
|
||||
print(shuffle(nums, n))
|
||||
# Output: [2,3,5,4,1,7]
|
||||
nums = [1, 2, 3, 4, 4, 3, 2, 1]
|
||||
n = 4
|
||||
print(shuffle(nums, n))
|
||||
# Output: [1,4,2,3,3,2,4,1]
|
||||
nums = [1, 1, 2, 2]
|
||||
n = 2
|
||||
print(shuffle(nums, n))
|
||||
# Output: [1,2,1,2]
|
67
data_structures/arrays/sorted_arrays_intersection.rb
Normal file
67
data_structures/arrays/sorted_arrays_intersection.rb
Normal file
|
@ -0,0 +1,67 @@
|
|||
# Given three integer arrays arr1, arr2 and arr3 sorted in strictly increasing order, return a sorted array of only the integers that appeared in all three arrays.
|
||||
#
|
||||
# Example 1:
|
||||
#
|
||||
# Input: arr1 = [1,2,3,4,5], arr2 = [1,2,5,7,9], arr3 = [1,3,4,5,8]
|
||||
# Output: [1,5]
|
||||
# Explanation: Only 1 and 5 appeared in the three arrays.
|
||||
#
|
||||
# Example 2:
|
||||
#
|
||||
# Input: arr1 = [197,418,523,876,1356], arr2 = [501,880,1593,1710,1870], arr3 = [521,682,1337,1395,1764]
|
||||
# Output: []
|
||||
#
|
||||
#
|
||||
|
||||
#
|
||||
# Approach: Two-pointers
|
||||
#
|
||||
|
||||
# Complexity Analysis
|
||||
#
|
||||
# Time Complexity: O(n), where n is the total length of all of the
|
||||
# input arrays.
|
||||
# Space Complexity: O(1), as we only initiate three integer variables
|
||||
# using constant space.
|
||||
|
||||
# @param {Integer[]} arr1
|
||||
# @param {Integer[]} arr2
|
||||
# @param {Integer[]} arr3
|
||||
# @return {Integer[]}
|
||||
def sorted_arrays_intersection(arr1, arr2, arr3)
|
||||
result = []
|
||||
|
||||
# prepare three pointers to iterate through three arrays
|
||||
# p1, p2, and p3 point to the beginning of arr1, arr2, and arr3 accordingly
|
||||
p1 = p2 = p3 = 0
|
||||
|
||||
while (p1 < arr1.count) && (p2 < arr2.count) && (p3 < arr3.count)
|
||||
if arr1[p1] == arr2[p2] && arr1[p1] == arr3[p3]
|
||||
result.push(arr1[p1])
|
||||
|
||||
p1 += 1
|
||||
p2 += 1
|
||||
p3 += 1
|
||||
elsif arr1[p1] < arr2[p2]
|
||||
p1 += 1
|
||||
elsif arr2[p2] < arr3[p3]
|
||||
p2 += 1
|
||||
else
|
||||
p3 += 1
|
||||
end
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
arr1 = [1, 2, 3, 4, 5]
|
||||
arr2 = [1, 2, 5, 7, 9]
|
||||
arr3 = [1, 3, 4, 5, 8]
|
||||
print(sorted_arrays_intersection(arr1, arr2, arr3))
|
||||
# Output: [1,5]
|
||||
|
||||
arr1 = [197, 418, 523, 876, 1356]
|
||||
arr2 = [501, 880, 1593, 1710, 1870]
|
||||
arr3 = [521, 682, 1337, 1395, 1764]
|
||||
print(sorted_arrays_intersection(arr1, arr2, arr3))
|
||||
# Output: []
|
45
data_structures/arrays/strings/anagram_checker.rb
Normal file
45
data_structures/arrays/strings/anagram_checker.rb
Normal file
|
@ -0,0 +1,45 @@
|
|||
# Challenge name: Is anagram
|
||||
#
|
||||
# Given two strings s and t , write a function to determine
|
||||
# if t is an anagram of s.
|
||||
#
|
||||
# Note:
|
||||
# You may assume the string contains only lowercase alphabets.
|
||||
#
|
||||
# Follow up:
|
||||
# What if the inputs contain unicode characters?
|
||||
# How would you adapt your solution to such case?
|
||||
#
|
||||
# @param {String} s
|
||||
# @param {String} t
|
||||
# @return {Boolean}
|
||||
|
||||
#
|
||||
# Approach: Sort and Compare
|
||||
#
|
||||
# Complexity analysis:
|
||||
#
|
||||
# Time Complexity: O(n log n). Assume that n is the length of s, sorting costs O(n log n), and comparing two strings costs O(n). Sorting time dominates and the overall time complexity is O(n log n).
|
||||
# Space Complexity: O(1). Space depends on the sorting implementation which, usually, costs O(1) auxiliary space if heapsort is used.
|
||||
#
|
||||
def is_anagram(s, t)
|
||||
return false if s.length != t.length
|
||||
|
||||
arr1 = s.split('').sort
|
||||
arr2 = t.split('').sort
|
||||
|
||||
arr1 == arr2
|
||||
end
|
||||
|
||||
s = 'anagram'
|
||||
t = 'nagaram'
|
||||
puts(is_anagram(s, t))
|
||||
# => true
|
||||
s = 'rat'
|
||||
t = 'car'
|
||||
puts(is_anagram(s, t))
|
||||
# => false
|
||||
s = 'a'
|
||||
t = 'ab'
|
||||
puts(is_anagram(s, t))
|
||||
# => false
|
127
data_structures/arrays/strings/palindrome.rb
Normal file
127
data_structures/arrays/strings/palindrome.rb
Normal file
|
@ -0,0 +1,127 @@
|
|||
# Challenge name: Valid Palindrome
|
||||
#
|
||||
# Given a string s, determine if it is a palindrome,
|
||||
# considering only alphanumeric characters and ignoring cases.
|
||||
#
|
||||
# Example 1:
|
||||
# Input: s = "A man, a plan, a canal: Panama"
|
||||
# Output: true
|
||||
# Explanation: "amanaplanacanalpanama" is a palindrome.
|
||||
#
|
||||
# Example 2:
|
||||
# Input: s = "race a car"
|
||||
# Output: false
|
||||
# Explanation: "raceacar" is not a palindrome.
|
||||
#
|
||||
# Constraints:
|
||||
# 1 <= s.length <= 2 * 105
|
||||
# s consists only of printable ASCII characters.
|
||||
# @param {String} s
|
||||
# @return {Boolean}
|
||||
|
||||
#
|
||||
# Approach 1: Using Ruby method .reverse
|
||||
#
|
||||
# Time Complexity: O(n)
|
||||
#
|
||||
def is_palindrome(s)
|
||||
letters_only = s.downcase.gsub(/[^0-9a-z]/i, '')
|
||||
letters_only.reverse == letters_only
|
||||
end
|
||||
|
||||
s = 'A man, a plan, a canal: Panama'
|
||||
puts is_palindrome(s)
|
||||
# Output: true
|
||||
# Explanation: "amanaplanacanalpanama" is a palindrome.
|
||||
|
||||
s = 'race a car'
|
||||
puts is_palindrome(s)
|
||||
# Output: false
|
||||
# Explanation: "raceacar" is not a palindrome.
|
||||
|
||||
s = 'ab_a'
|
||||
puts is_palindrome(s)
|
||||
# Output: true
|
||||
# Explanation: "aba" is a palindrome.
|
||||
|
||||
#
|
||||
# Approach 2: Reversed array
|
||||
#
|
||||
# Complexity Analysis:
|
||||
#
|
||||
# Time Complexity: O(n), in length n of the string.
|
||||
#
|
||||
# We need to iterate through the string: When we filter out non-alphanumeric characters and convert the remaining
|
||||
# characters to lower-case. When we reverse the string. When we compare the original and the reversed strings.
|
||||
# Each iteration runs linearly in time (since each character operation completes in constant time).
|
||||
# Thus, the effective run-time complexity is linear.
|
||||
#
|
||||
# Space Complexity: O(n), in length n of the string. We need O(n) additional
|
||||
# space to store the filtered string and the reversed string.
|
||||
#
|
||||
def is_palindrome(s)
|
||||
letters_only_array = s.downcase.gsub(/[^0-9a-z]/i, '').split('')
|
||||
reversed_array = []
|
||||
letters_only_array.each do |letter|
|
||||
reversed_array.unshift(letter)
|
||||
end
|
||||
letters_only_array == reversed_array
|
||||
end
|
||||
|
||||
s = 'A man, a plan, a canal: Panama'
|
||||
puts is_palindrome(s)
|
||||
# Output: true
|
||||
# Explanation: "amanaplanacanalpanama" is a palindrome.
|
||||
|
||||
s = 'race a car'
|
||||
puts is_palindrome(s)
|
||||
# Output: false
|
||||
# Explanation: "raceacar" is not a palindrome.
|
||||
|
||||
s = 'ab_a'
|
||||
puts is_palindrome(s)
|
||||
# Output: true
|
||||
# Explanation: "aba" is a palindrome.
|
||||
|
||||
#
|
||||
# Approach 2: Two Pointers
|
||||
#
|
||||
|
||||
#
|
||||
# Complexity Analysis:
|
||||
#
|
||||
# Time Complexity: O(n), in length n of the string. We traverse over each
|
||||
# character at most once until the two pointers meet in the middle, or when
|
||||
# we break and return early.
|
||||
# Space Complexity: O(1). No extra space required, at all.
|
||||
#
|
||||
def is_palindrome(s)
|
||||
letters_only = s.downcase.gsub(/[^0-9a-z]/i, '')
|
||||
p1 = 0
|
||||
p2 = letters_only.length - 1
|
||||
|
||||
while p1 < p2
|
||||
if letters_only[p1] == letters_only[p2]
|
||||
p1 += 1
|
||||
p2 -= 1
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
s = 'A man, a plan, a canal: Panama'
|
||||
puts is_palindrome(s)
|
||||
# Output: true
|
||||
# Explanation: "amanaplanacanalpanama" is a palindrome.
|
||||
|
||||
s = 'race a car'
|
||||
puts is_palindrome(s)
|
||||
# Output: false
|
||||
# Explanation: "raceacar" is not a palindrome.
|
||||
|
||||
s = 'ab_a'
|
||||
puts is_palindrome(s)
|
||||
# Output: true
|
||||
# Explanation: "aba" is a palindrome.
|
76
data_structures/arrays/strings/remove_vowels.rb
Normal file
76
data_structures/arrays/strings/remove_vowels.rb
Normal file
|
@ -0,0 +1,76 @@
|
|||
# Challenge name: Remove vowels from a string
|
||||
#
|
||||
# Given a string s, remove the vowels 'a', 'e', 'i', 'o', and 'u'
|
||||
# from it, and return the new string.
|
||||
#
|
||||
# Example 1:
|
||||
# Input: s = "leetcodeisacommunityforcoders"
|
||||
# Output: "ltcdscmmntyfrcdrs"
|
||||
#
|
||||
# Example 2:
|
||||
# Input: s = "aeiou"
|
||||
# Output: ""
|
||||
#
|
||||
# @param {String} s
|
||||
# @return {String}
|
||||
|
||||
#
|
||||
# Approach 1: Brute Force
|
||||
#
|
||||
# Time Complexity: O(n)
|
||||
#
|
||||
|
||||
def remove_vowels(s)
|
||||
result_array = []
|
||||
s.downcase!
|
||||
start_array = s.split('')
|
||||
|
||||
start_array.each do |letter|
|
||||
if letter != 'a' && letter != 'e' && letter != 'i' && letter != 'o' && letter != 'u'
|
||||
result_array.push(letter)
|
||||
end
|
||||
end
|
||||
|
||||
result_array.join('')
|
||||
end
|
||||
|
||||
s = 'leetcodeisacommunityforcoders'
|
||||
puts(remove_vowels(s))
|
||||
# => "ltcdscmmntyfrcdrs"
|
||||
s = 'aeiou'
|
||||
puts(remove_vowels(s))
|
||||
# => ""
|
||||
|
||||
#
|
||||
# Approach 2: Regex
|
||||
#
|
||||
# Time Complexity: O(n)
|
||||
#
|
||||
def remove_vowels(s)
|
||||
vowels = /[aeiou]/i
|
||||
s.gsub!(vowels, '')
|
||||
s
|
||||
end
|
||||
|
||||
s = 'leetcodeisacommunityforcoders'
|
||||
puts(remove_vowels(s))
|
||||
# => "ltcdscmmntyfrcdrs"
|
||||
s = 'aeiou'
|
||||
puts(remove_vowels(s))
|
||||
# => ""
|
||||
|
||||
#
|
||||
# Approach 3: Using Ruby .delete() method
|
||||
#
|
||||
# Time Complexity: O(n)
|
||||
#
|
||||
def remove_vowels(s)
|
||||
s.downcase.delete('aeiou')
|
||||
end
|
||||
|
||||
s = 'leetcodeisacommunityforcoders'
|
||||
puts(remove_vowels(s))
|
||||
# => "ltcdscmmntyfrcdrs"
|
||||
s = 'aeiou'
|
||||
puts(remove_vowels(s))
|
||||
# => ""
|
|
@ -86,48 +86,3 @@ print(two_sum([3, 2, 4], 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
|
||||
|
||||
if hash[difference_target] && hash[difference_target] != i
|
||||
return [i, hash[difference_target]]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
nums = [2, 7, 11, 15]
|
||||
target = 9
|
||||
print(two_sum(nums, target))
|
||||
# => [0,1]
|
||||
|
||||
nums = [3, 2, 4]
|
||||
target = 6
|
||||
print(two_sum(nums, target))
|
||||
# => [1,2]
|
||||
|
||||
nums = [3, 3]
|
||||
target = 6
|
||||
print(two_sum(nums, target))
|
||||
# => [0,1]
|
||||
|
|
161
data_structures/hash_table/anagram_checker.rb
Normal file
161
data_structures/hash_table/anagram_checker.rb
Normal file
|
@ -0,0 +1,161 @@
|
|||
# Challenge name: Is anagram
|
||||
#
|
||||
# Given two strings s and t , write a function to determine
|
||||
# if t is an anagram of s.
|
||||
#
|
||||
# Note:
|
||||
# You may assume the string contains only lowercase alphabets.
|
||||
#
|
||||
# Follow up:
|
||||
# What if the inputs contain unicode characters?
|
||||
# How would you adapt your solution to such case?
|
||||
#
|
||||
# @param {String} s
|
||||
# @param {String} t
|
||||
# @return {Boolean}
|
||||
|
||||
#
|
||||
# Approach: Hash table
|
||||
#
|
||||
|
||||
# Complexity analysis:
|
||||
#
|
||||
# Time complexity: O(n). Time complexity is O(n) since accessing the counter
|
||||
# table is a constant time operation.
|
||||
# Space complexity: O(1). Although we do use extra space,
|
||||
# the space complexity is O(1) because the table's size stays constant no
|
||||
# matter how large n is.
|
||||
#
|
||||
def is_anagram(s, t)
|
||||
s_length = s.length
|
||||
t_length = t.length
|
||||
counter = Hash.new(0)
|
||||
|
||||
return false unless s_length == t_length
|
||||
|
||||
(0...s_length).each do |i|
|
||||
counter[s[i]] += 1
|
||||
counter[t[i]] -= 1
|
||||
end
|
||||
|
||||
counter.each do |k, v|
|
||||
return false unless v == 0
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
s = 'anagram'
|
||||
t = 'nagaram'
|
||||
puts(is_anagram(s, t))
|
||||
# => true
|
||||
|
||||
s = 'rat'
|
||||
t = 'car'
|
||||
puts(is_anagram(s, t))
|
||||
# => false
|
||||
|
||||
s = 'a'
|
||||
t = 'ab'
|
||||
puts(is_anagram(s, t))
|
||||
# => false
|
||||
|
||||
#
|
||||
# Approach 2: Hash table
|
||||
#
|
||||
|
||||
# Algorithm: we could also first increment the counter for s,
|
||||
# then decrement the counter for t. If at any point the counter
|
||||
# drops below zero, we know that t contains an extra letter,
|
||||
# not in s, and return false immediately.
|
||||
|
||||
# Complexity analysis:
|
||||
#
|
||||
# Time complexity: O(n).
|
||||
# Space complexity: O(1).
|
||||
#
|
||||
|
||||
def is_anagram(s, t)
|
||||
s_length = s.length
|
||||
t_length = t.length
|
||||
counter = Hash.new(0)
|
||||
|
||||
return false unless s_length == t_length
|
||||
|
||||
(0...s_length).each do |i|
|
||||
counter[s[i]] += 1
|
||||
end
|
||||
|
||||
(0...s_length).each do |i|
|
||||
counter[t[i]] -= 1
|
||||
|
||||
return false if counter[t[i]] < 0
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
s = 'anagram'
|
||||
t = 'nagaram'
|
||||
puts(is_anagram(s, t))
|
||||
# => true
|
||||
|
||||
s = 'rat'
|
||||
t = 'car'
|
||||
puts(is_anagram(s, t))
|
||||
# => false
|
||||
|
||||
s = 'a'
|
||||
t = 'ab'
|
||||
puts(is_anagram(s, t))
|
||||
# => false
|
||||
|
||||
#
|
||||
# Approach 3: populate 2 hashes and compare them
|
||||
#
|
||||
|
||||
def is_anagram(s, t)
|
||||
s = s.chars
|
||||
t = t.chars
|
||||
|
||||
return false if s.count != t.count
|
||||
|
||||
hash1 = {}
|
||||
s.each do |value|
|
||||
hash1[value] = if hash1[value]
|
||||
hash1[value] + 1
|
||||
else
|
||||
1
|
||||
end
|
||||
end
|
||||
|
||||
hash2 = {}
|
||||
t.each do |value|
|
||||
hash2[value] = if hash2[value]
|
||||
hash2[value] + 1
|
||||
else
|
||||
1
|
||||
end
|
||||
end
|
||||
|
||||
hash1.keys.each do |key|
|
||||
return false if hash2[key] != hash1[key]
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
s = 'anagram'
|
||||
t = 'nagaram'
|
||||
puts(is_anagram(s, t))
|
||||
# => true
|
||||
|
||||
s = 'rat'
|
||||
t = 'car'
|
||||
puts(is_anagram(s, t))
|
||||
# => false
|
||||
|
||||
s = 'a'
|
||||
t = 'ab'
|
||||
puts(is_anagram(s, t))
|
||||
# => false
|
56
data_structures/hash_table/arrays_intersection.rb
Normal file
56
data_structures/hash_table/arrays_intersection.rb
Normal file
|
@ -0,0 +1,56 @@
|
|||
# Given three integer arrays arr1, arr2 and arr3 sorted in strictly increasing order, return a sorted array of only the integers that appeared in all three arrays.
|
||||
#
|
||||
# Example 1:
|
||||
#
|
||||
# Input: arr1 = [1,2,3,4,5], arr2 = [1,2,5,7,9], arr3 = [1,3,4,5,8]
|
||||
# Output: [1,5]
|
||||
# Explanation: Only 1 and 5 appeared in the three arrays.
|
||||
#
|
||||
# Example 2:
|
||||
#
|
||||
# Input: arr1 = [197,418,523,876,1356], arr2 = [501,880,1593,1710,1870], arr3 = [521,682,1337,1395,1764]
|
||||
# Output: []
|
||||
#
|
||||
#
|
||||
|
||||
#
|
||||
# Approach: Hash table
|
||||
#
|
||||
|
||||
# Complexity Analysis
|
||||
|
||||
# Time Complexity: O(n) - n is the total length of
|
||||
# all of the input arrays.
|
||||
# Space Complexity: O(n) - n is the total length of all of the
|
||||
# input arrays. This is because we adopted a Hash table to store all
|
||||
# numbers and their number of appearances as values.
|
||||
|
||||
def arrays_intersection(arr1, arr2, arr3)
|
||||
hash = Hash.new(0)
|
||||
|
||||
add_to_hash(arr1, hash)
|
||||
add_to_hash(arr2, hash)
|
||||
add_to_hash(arr3, hash)
|
||||
|
||||
hash.select { |key, value| value == 3 }.keys
|
||||
end
|
||||
|
||||
def add_to_hash(arr, hash)
|
||||
arr.count.times do |pointer|
|
||||
value = arr[pointer]
|
||||
hash[value] += 1
|
||||
end
|
||||
end
|
||||
|
||||
arr1 = [1, 2, 3, 4, 5]
|
||||
arr2 = [1, 2, 5, 7, 9]
|
||||
arr3 = [1, 3, 4, 5, 8]
|
||||
print arrays_intersection(arr1, arr2, arr3)
|
||||
# Output: [1,5]
|
||||
# Explanation: Only 1 and 5 appeared in the three arrays.
|
||||
|
||||
arr1 = [197, 418, 523, 876, 1356]
|
||||
arr2 = [501, 880, 1593, 1710, 1870]
|
||||
arr3 = [521, 682, 1337, 1395, 1764]
|
||||
print arrays_intersection(arr1, arr2, arr3)
|
||||
# Output: []
|
|
@ -0,0 +1,61 @@
|
|||
# Find All Duplicates in an Array
|
||||
#
|
||||
# Given an array of integers, 1 ≤ a[i] ≤ n (n = size of array),
|
||||
# some elements appear twice and others appear once.
|
||||
#
|
||||
# Find all the elements that appear twice in this array.
|
||||
#
|
||||
# Could you do it without extra space and in O(n) runtime?
|
||||
#
|
||||
# Example:
|
||||
# Input:
|
||||
# [4,3,2,7,8,2,3,1]
|
||||
#
|
||||
# Output:
|
||||
# [2,3]
|
||||
|
||||
require 'benchmark'
|
||||
|
||||
array = [4, 3, 2, 7, 8, 2, 3, 1]
|
||||
long_array = [4, 3, 2, 7, 8, 2, 3, 1] * 100
|
||||
|
||||
#
|
||||
# Approach: Hash table
|
||||
#
|
||||
|
||||
#
|
||||
# Complexity Analysis
|
||||
#
|
||||
# Time complexity: O(n) average case.
|
||||
#
|
||||
|
||||
def find_duplicates(array)
|
||||
result_hash = {}
|
||||
result_array = []
|
||||
|
||||
# loop through array and build a hash with counters
|
||||
# where the key is the array element and the counter is the value
|
||||
# increase counter when duplicate is found
|
||||
array.each do |num|
|
||||
if result_hash[num].nil?
|
||||
result_hash[num] = 1
|
||||
else
|
||||
result_hash[num] += 1
|
||||
end
|
||||
end
|
||||
|
||||
# loop through hash and look for values > 1
|
||||
result_hash.each do |k, v|
|
||||
result_array.push(k) if v > 1
|
||||
end
|
||||
|
||||
# return keys
|
||||
result_array
|
||||
end
|
||||
|
||||
Benchmark.bmbm do |x|
|
||||
x.report('execute algorithm 3') do
|
||||
print(find_duplicates(array))
|
||||
print(find_duplicates(long_array))
|
||||
end
|
||||
end
|
59
data_structures/hash_table/richest_customer_wealth.rb
Normal file
59
data_structures/hash_table/richest_customer_wealth.rb
Normal file
|
@ -0,0 +1,59 @@
|
|||
# Challenge name: Richest Customer Wealth
|
||||
#
|
||||
# You are given an m x n integer grid accounts where accounts[i][j]
|
||||
# is the amount of money the ith customer has in the jth bank.
|
||||
#
|
||||
# Return the wealth that the richest customer has.
|
||||
# A customer's wealth is the amount of money they have in all
|
||||
# their bank accounts. The richest customer is the customer that
|
||||
# has the maximum wealth.
|
||||
#
|
||||
# Example 1:
|
||||
# Input: accounts = [[1,2,3],[3,2,1]]
|
||||
# Output: 6
|
||||
# Explanation:
|
||||
# 1st customer has wealth = 1 + 2 + 3 = 6
|
||||
# 2nd customer has wealth = 3 + 2 + 1 = 6
|
||||
# Both customers are considered the richest with a wealth of 6
|
||||
# each, so return 6.
|
||||
#
|
||||
# Example 2:
|
||||
# Input: accounts = [[1,5],[7,3],[3,5]]
|
||||
# Output: 10
|
||||
# Explanation:
|
||||
# 1st customer has wealth = 6
|
||||
# 2nd customer has wealth = 10
|
||||
# 3rd customer has wealth = 8
|
||||
# The 2nd customer is the richest with a wealth of 10.
|
||||
#
|
||||
# Example 3:
|
||||
# Input: accounts = [[2,8,7],[7,1,3],[1,9,5]]
|
||||
# Output: 17
|
||||
|
||||
#
|
||||
# Approach: Hash
|
||||
#
|
||||
# Time Complexity: O(n)
|
||||
#
|
||||
def find_richest_customer_wealth(accounts)
|
||||
result_hash = {}
|
||||
accounts.each_with_index do |customer, i|
|
||||
result_hash[i] = customer.sum
|
||||
end
|
||||
|
||||
highest_value = 0
|
||||
result_hash.each do |k, v|
|
||||
if v > highest_value
|
||||
highest_value = v
|
||||
end
|
||||
end
|
||||
|
||||
highest_value
|
||||
end
|
||||
|
||||
puts find_richest_customer_wealth([[1,2,3],[3,2,1]])
|
||||
# => 6
|
||||
puts find_richest_customer_wealth([[1,5],[7,3],[3,5]])
|
||||
# => 10
|
||||
puts find_richest_customer_wealth([[2,8,7],[7,1,3],[1,9,5]])
|
||||
# => 17
|
70
data_structures/hash_table/two_sum.rb
Normal file
70
data_structures/hash_table/two_sum.rb
Normal file
|
@ -0,0 +1,70 @@
|
|||
# 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.
|
||||
#
|
||||
# You can return the answer in any order.
|
||||
#
|
||||
#
|
||||
# Examples
|
||||
#
|
||||
# Input: nums = [2, 7, 11, 15], target = 9
|
||||
# Output: [0,1]
|
||||
# Explanation: Because nums[0] + nums[1] == 9, we return [0, 1].
|
||||
#
|
||||
# Input: nums = [3, 2, 4], target = 6
|
||||
# Output: [1,2]
|
||||
#
|
||||
# Input: nums = [3, 3], target = 6
|
||||
# Output: [0,1]
|
||||
# Explanation: Because nums[0] + nums[1] == 9, we return [0, 1].
|
||||
#
|
||||
# @param {Integer[]} nums
|
||||
# @param {Integer} target
|
||||
# @return {Integer[]}
|
||||
|
||||
#
|
||||
# Approach: Using Hash table
|
||||
#
|
||||
|
||||
# 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
|
||||
|
||||
if hash[difference_target] && hash[difference_target] != i
|
||||
return [i, hash[difference_target]]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
nums = [2, 7, 11, 15]
|
||||
target = 9
|
||||
print(two_sum(nums, target))
|
||||
# => [0,1]
|
||||
|
||||
nums = [3, 2, 4]
|
||||
target = 6
|
||||
print(two_sum(nums, target))
|
||||
# => [1,2]
|
||||
|
||||
nums = [3, 3]
|
||||
target = 6
|
||||
print(two_sum(nums, target))
|
||||
# => [0,1]
|
31
maths/factorial.rb
Normal file
31
maths/factorial.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
=begin
|
||||
A ruby program calculate factorial of a given number.
|
||||
Mathematical Explanation: The factorial of a number is the product of all the integers from 1 to that number.
|
||||
i.e: n! = n*(n-1)*(n-2)......*2*1
|
||||
=end
|
||||
|
||||
#
|
||||
# Approach: Interative
|
||||
#
|
||||
|
||||
def factorial(n)
|
||||
return nil if n < 0
|
||||
|
||||
fac = 1
|
||||
|
||||
while n > 0
|
||||
fac *= n
|
||||
n -= 1
|
||||
end
|
||||
|
||||
fac
|
||||
end
|
||||
|
||||
puts '4! = ' + factorial(4).to_s
|
||||
# 4! = 24
|
||||
|
||||
puts '0! = ' + factorial(0).to_s
|
||||
# 0! = 1
|
||||
|
||||
puts '10! = ' + factorial(10).to_s
|
||||
# 10! = 3628800
|
|
@ -8,18 +8,21 @@ def binary_search(array, key)
|
|||
return middle if array[middle] == key
|
||||
|
||||
if key < array[middle]
|
||||
back = middle - 1
|
||||
else
|
||||
front = middle + 1
|
||||
end
|
||||
back = middle - 1
|
||||
else
|
||||
front = middle + 1
|
||||
end
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
puts "Enter a sorted space-separated list:"
|
||||
arr = gets.chomp.split(' ').map(&:to_i)
|
||||
|
||||
puts "Enter the value to be searched:"
|
||||
value = gets.chomp.to_i
|
||||
|
||||
puts if binary_search(arr, value) != nil
|
||||
"Found at index #{binary_search(arr, value)}"
|
||||
else
|
65
sorting/sort_color.rb
Normal file
65
sorting/sort_color.rb
Normal file
|
@ -0,0 +1,65 @@
|
|||
# Given an array nums with n objects colored red, white, or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white, and blue.
|
||||
#
|
||||
# We will use the integers 0, 1, and 2 to represent the color red, white, and blue, respectively.
|
||||
#
|
||||
# Example 1:
|
||||
#
|
||||
# Input: nums = [2,0,2,1,1,0]
|
||||
# Output: [0,0,1,1,2,2]
|
||||
#
|
||||
# Example 2:
|
||||
#
|
||||
# Input: nums = [2,0,1]
|
||||
# Output: [0,1,2]
|
||||
#
|
||||
# Example 3:
|
||||
#
|
||||
# Input: nums = [0]
|
||||
# Output: [0]
|
||||
#
|
||||
# Example 4:
|
||||
#
|
||||
# Input: nums = [1]
|
||||
# Output: [1]
|
||||
|
||||
# @param {Integer[]} nums
|
||||
# @return {Void} Do not return anything, modify nums in-place instead.
|
||||
def sort_colors(nums)
|
||||
bubble_sort(nums)
|
||||
end
|
||||
|
||||
def bubble_sort(array)
|
||||
array_length = array.size
|
||||
return array if array_length <= 1
|
||||
|
||||
loop do
|
||||
swapped = false
|
||||
|
||||
(array_length - 1).times do |i|
|
||||
if array[i] > array[i + 1]
|
||||
array[i], array[i + 1] = array[i + 1], array[i]
|
||||
swapped = true
|
||||
end
|
||||
end
|
||||
|
||||
break unless swapped
|
||||
end
|
||||
|
||||
array
|
||||
end
|
||||
|
||||
nums = [2, 0, 2, 1, 1, 0]
|
||||
puts sort_colors(nums)
|
||||
# Output: [0,0,1,1,2,2]
|
||||
|
||||
nums = [2, 0, 1]
|
||||
puts sort_colors(nums)
|
||||
# Output: [0,1,2]
|
||||
|
||||
nums = [0]
|
||||
puts sort_colors(nums)
|
||||
# Output: [0]
|
||||
|
||||
nums = [1]
|
||||
puts sort_colors(nums)
|
||||
# Output: [1]
|
Loading…
Reference in a new issue