Reputation: 29
I am trying to write a function in kotlin that checks if all characters in the string are unique.
fun isUnique(s: String): Boolean {
return s.filter {
char -> s.count(char) == 1
} == s
}
I would like to know what is the runtime complexity of this method. Is it O(n) or O(n pow2) (because we touch each char twice in the filter function and in the count function)? Also is the space complexity O(1)?
Alternatively, I wrote this method
fun isUnique2(s: String): Boolean {
return s.groupBy {
char -> s.count(char)
}.filterKeys{key > 1}.isEmpty()
}
what are the space and time complexity of this method?
I appreciate any help
Thank you
Upvotes: 1
Views: 540
Reputation: 37799
The first implementation is O(n^2), not simply because you touch each char twice (it's actually 4 times because of ==
, but could be just twice if you compared sizes instead), but because for each char you consider in the filter, you iterate the whole N characters of the string via count()
.
It's not the same to iterate the string twice, and to iterate the string once per char of the string. This is the difference between O(2n) (= O(n)) and O(n^2).
This first implementation also allocates an extra collection with filtered elements, which in the worst case contains all chars, so O(n) space.
The second implementation does even more work, you still start with an O(n^2) step because you count
through the whole string to build each group. But then you add more space complexity because you allocate more intermediate collections.
You can have an O(n) solution, with O(n) space by simply turning your string into a Set
and comparing sizes:
fun isUnique(s: String): Boolean {
return s.toSet().size == s.length
}
Internally, toSet()
uses a LinkedHashSet
, for which insertion has an amortized cost of O(1). This means the string is iterated only once, and each char is inserted in O(1) into the set, which ensures at insertion time that there are no duplicates. Comparing sizes is also O(1) in general because most collections have a constant-cost way to access their size.
Upvotes: 1
Reputation: 7902
Both implementations have O(n^2) time complexity and O(n) space complexity.
With the following solution you can have O(n) time complexity (keeping O(n) space) in the worst case:
fun isUnique(s: String): Boolean {
val hashset = hashSetOf<Char>()
return s.all { hashset.add(it) }
}
But generally this algorithm may end up (returning false
) before reaching end of the string (if we met some repeating char, no need to check remaining chars), so in the best case it may end on the 2-nd iteration.
The magic behind this consists of two parts:
add
method of Set
returns false
if this set already contained the specified elementall
method returns false
on the first predicate, which evaluated to false
Upvotes: 2