Actually, if you go into fully pedantic mode, the set version is worse. Hash-based set insertion is commonly taken to be O(1), but that depends on hash comparison being O(1), which depends on using single-word hash values, which means your n is bounded by eg 2^63 (50% occupancy) or whatever. Honestly fine in practice, but hash lookup isn't "as" O(1) as indexing into an array. (ie, it requires a less realistic cost model.)
You also need your keys' length to be bounded by a constant. Otherwise just hashing everything will exceed O(n).
In reality random indexing is O(sqrt(n)) for 2D memory chips, and at best O(cbrt(n)) in our 3D physical world.
let mut hash_set = HashSet::new();
let mut len = 0;
for i in 0..arr.len() {
if !hash_set.contains(&arr[i]) {
hash_set.insert(arr[i]);
arr[len] = arr[i];
len += 1;
}
}
arr.truncate(len);You can also use radix sort for what I'd like to call "fake" O(n) sort since physical hardware puts an upper limit on the hidden constant.