mirror of
https://github.com/TheAlgorithms/Ruby
synced 2025-01-13 08:01:03 +01:00
Merge branch 'master' into jk-intersection
This commit is contained in:
commit
25d76f8944
20 changed files with 762 additions and 13 deletions
28
DIRECTORY.md
28
DIRECTORY.md
|
@ -1,4 +1,7 @@
|
|||
|
||||
## 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)
|
||||
|
||||
|
@ -16,14 +19,17 @@
|
|||
* [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)
|
||||
* [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)
|
||||
|
@ -33,6 +39,8 @@
|
|||
* [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)
|
||||
|
@ -59,13 +67,17 @@
|
|||
## 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)
|
||||
* [Fibonacci](https://github.com/TheAlgorithms/Ruby/blob/master/maths/fibonacci.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)
|
||||
|
@ -98,14 +110,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)
|
||||
|
|
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: ["()"]
|
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]
|
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: []
|
|
@ -15,7 +15,7 @@
|
|||
# @return {Boolean}
|
||||
|
||||
#
|
||||
# Approach 1: Sort and Compare
|
||||
# Approach: Sort and Compare
|
||||
#
|
||||
# Complexity analysis:
|
||||
#
|
||||
|
|
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.
|
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: []
|
34
maths/add.rb
Normal file
34
maths/add.rb
Normal file
|
@ -0,0 +1,34 @@
|
|||
# A ruby program to add numbers
|
||||
# Addition or sum of numbers means adding each and every element of the inputs
|
||||
# Sum or addition of 1 and 3 is 1 + 3 = 4
|
||||
|
||||
def add(*array)
|
||||
sum = 0
|
||||
array.each { |a| sum+=a }
|
||||
puts "The sum of following elements #{array} is #{sum}"
|
||||
rescue
|
||||
puts "Error: Please provide number only!"
|
||||
end
|
||||
|
||||
#
|
||||
# Valid inputs
|
||||
#
|
||||
|
||||
puts add(1)
|
||||
# The sum of following elements [1] is 1
|
||||
|
||||
puts add(2, 5, -4)
|
||||
# The sum of following elements [2, 5, -4] is 3
|
||||
|
||||
puts add(25, 45)
|
||||
# The sum of following elements [25, 45] is 70
|
||||
|
||||
#
|
||||
# Invalid inputs
|
||||
#
|
||||
|
||||
puts add("1", 2, 3)
|
||||
# Error: Please provide number only!
|
||||
|
||||
puts add("a", 1)
|
||||
# Error: Please provide number only!
|
28
maths/average_mean.rb
Normal file
28
maths/average_mean.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
# A ruby program for finding average mean
|
||||
|
||||
module AverageMean
|
||||
# Average mean = sum of elements / total number of elements
|
||||
def self.average_mean(n, *array)
|
||||
if n.instance_of? Integer
|
||||
if n == array.size
|
||||
puts "The average mean of the following elements #{array} is #{array.sum/array.size}."
|
||||
else
|
||||
puts "Provide the required #{n} elements properly!"
|
||||
end
|
||||
else
|
||||
raise
|
||||
end
|
||||
rescue
|
||||
puts "Error: Please provide number only!"
|
||||
end
|
||||
end
|
||||
|
||||
# Valid inputs
|
||||
AverageMean.average_mean(2, 3, 1)
|
||||
AverageMean.average_mean(5, 1, 2, 3, 4, 5)
|
||||
AverageMean.average_mean(3, 2, 2, 2)
|
||||
|
||||
# Invalid inputs
|
||||
AverageMean.average_mean(2, 3, 1, 5)
|
||||
AverageMean.average_mean(2, 3, "a")
|
||||
AverageMean.average_mean("a", 1, 2)
|
60
maths/average_median.rb
Normal file
60
maths/average_median.rb
Normal file
|
@ -0,0 +1,60 @@
|
|||
# A ruby program to find average median
|
||||
# Reference: https://dev.to/colerau/how-to-find-the-median-and-mean-of-an-array-in-ruby-4f04
|
||||
|
||||
module AverageMedian
|
||||
def self.average_median(n, *array)
|
||||
if n.instance_of? Integer
|
||||
if n == array.size
|
||||
array.sort
|
||||
if array.size % 2 == 0
|
||||
mid_element_1 = array.size/2
|
||||
mid_element_2 = mid_element_1 + 1
|
||||
puts "The average median of the following elements #{array} is #{(array[mid_element_1 - 1] + array[mid_element_2 - 1]) / 2}."
|
||||
else
|
||||
mid_element = (array.size + 1) / 2
|
||||
puts "The average median of the following elements #{array} is #{array[mid_element - 1]}."
|
||||
end
|
||||
else
|
||||
puts "Provide the required #{n} elements properly!"
|
||||
end
|
||||
else
|
||||
raise
|
||||
end
|
||||
rescue
|
||||
puts "Error: Please provide number only!"
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Valid inputs
|
||||
#
|
||||
|
||||
puts AverageMedian.average_median(2, 3, 1)
|
||||
# The average median of the following elements [3, 1] is 2.
|
||||
|
||||
puts AverageMedian.average_median(5, 1, 2, 3, 4, 5)
|
||||
# The average median of the following elements [1, 2, 3, 4, 5] is 3.
|
||||
|
||||
puts AverageMedian.average_median(3, 2, 2, 2)
|
||||
# The average median of the following elements [2, 2, 2] is 2.
|
||||
|
||||
puts AverageMedian.average_median(1, 5)
|
||||
# The average median of the following elements [5] is 5.
|
||||
|
||||
#
|
||||
# Invalid inputs
|
||||
#
|
||||
|
||||
puts AverageMedian.average_median(2, 3, 1, 5)
|
||||
# Provide the required 2 elements properly!
|
||||
|
||||
puts AverageMedian.average_median(2, 3, "a")
|
||||
# Traceback (most recent call last):
|
||||
# 4: from /Users/voliveira/.rvm/rubies/ruby-2.7.0/bin/irb:23:in `<main>'
|
||||
# 3: from /Users/voliveira/.rvm/rubies/ruby-2.7.0/bin/irb:23:in `load'
|
||||
# 2: from /Users/voliveira/.rvm/rubies/ruby-2.7.0/lib/ruby/gems/2.7.0/gems/irb-1.2.1/exe/irb:11:in `<top (required)>'
|
||||
# 1: from (irb):30
|
||||
# NameError (undefined local variable or method `verageMedian' for main:Object)
|
||||
|
||||
puts AverageMedian.average_median("a", 1, 2)
|
||||
# Error: Please provide number only!
|
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
|
Loading…
Reference in a new issue