Merge branch 'master' into master

This commit is contained in:
Sahil Afrid Farookhi 2021-04-28 15:07:53 +05:30 committed by GitHub
commit d3d66e1ef1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 1321 additions and 99 deletions

View file

@ -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)

View 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: ["()"]

View file

@ -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

View 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]

View 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]

View 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

View 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]

View 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: []

View 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

View 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.

View 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))
# => ""

View file

@ -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]

View 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

View 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: []

View file

@ -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

View 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

View 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
View 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

View file

@ -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
View 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]