Reputation: 73
I have written this algorithm here and I am trying to evaluate its time and space complexity in terms of Big-O notation. The algorithm determines if two given strings are anagrams.
def anagram(str1, str2)
str1.each_char do |char|
selected_index = str2.index(char)
return false if !selected_index #to handle nil index
str2.slice!(selected_index)
end
str2.empty?
end
The time complexity of this function is O(n^2)
, and the space complexity is O(1)
? I believe I may be mistaken for the space complexity (could be O(n)
) because the selected_index
variable is repeatedly re-assigned which takes up memory relative to how long the each_char
loop runs for.
If someone could please throw some guidance that would be great :)
Upvotes: 3
Views: 585
Reputation: 12229
Gathering up all those comments into an answer, here is my analysis:
Time
The algorithm as presented does indeed have O(n^2)
running time.
The body of the loop is executed n
times and takes linear time for index
, linear time for slice
, and constant time for the rest, requiring a total of O(n^2)
time.
Space
The algoithm as presented requires linear space, because it updates a copy of str2
at each iteration.
The rest of the algorithm only takes constant space, unless you include the storage for the inputs themselves, which is also linear.
Faster algorithm: sort str1
and str2
A faster algorithm would be to do string compare sort-by-character(str1)
and sort-by-character(str2)
. That would take O(n log n)
time and O(n)
space for the sort; and linear time and constant space for the comparison, for an overall O(n log n)
time and O(n)
space.
Even faster algorithm: use a hash (proposed by OP in the comments)
Using hash tables to store character and then compare character counts can reduce the running time to O(n)
, assuming standard O(1)
insert and lookup hash operations. The space in this case is the space required for the hash tables, which is O(k)
for a character alphabet of size k
, which can be considered constant if k
is fixed. Of course, the input parameters still consume their initial O(n)
space as they are passed in or where they are originally stored; the O(k)
reflects only the additional space required to run this algorithm.
Upvotes: 2