TheAlgorithms-Ruby/data_structures/hash_table/anagram_checker.rb

162 lines
2.7 KiB
Ruby
Raw Normal View History

2021-04-01 04:02:57 +02:00
# 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
#
2021-04-01 18:42:45 +02:00
2021-04-01 04:02:57 +02:00
# Complexity analysis:
#
2021-04-01 04:04:39 +02:00
# 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.
2021-04-01 04:02:57 +02:00
#
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
2021-09-03 22:24:58 +02:00
counter.each do |_k, v|
2021-04-01 04:02:57 +02:00
return false unless v == 0
end
true
end
s = 'anagram'
t = 'nagaram'
puts(is_anagram(s, t))
# => true
2021-04-01 04:04:39 +02:00
2021-04-01 04:02:57 +02:00
s = 'rat'
t = 'car'
puts(is_anagram(s, t))
# => false
2021-04-01 04:04:39 +02:00
2021-04-01 04:02:57 +02:00
s = 'a'
t = 'ab'
puts(is_anagram(s, t))
# => false
2021-04-01 18:36:46 +02:00
#
# 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
2021-04-01 18:36:52 +02:00
2021-04-01 18:38:27 +02:00
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
2021-04-01 18:36:52 +02:00
#
# 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 = {}
2021-04-01 18:38:27 +02:00
s.each do |value|
2021-04-01 18:36:52 +02:00
hash1[value] = if hash1[value]
hash1[value] + 1
else
1
end
end
hash2 = {}
2021-04-01 18:38:27 +02:00
t.each do |value|
2021-04-01 18:36:52 +02:00
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
2021-04-01 18:38:27 +02:00
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