Since elem
is O(n), the solutions based on using it to check each element are O(n^2).
The "standard" efficient solution to the duplicates problem is to sort the list before checking for duplicates. Here, since we need to preserve elements, we have to be a bit more careful.
import Data.List
import Data.Ord
rmdupSorted :: Eq b => [(a,b)] -> [(a,b)]
rmdupSorted (x@(_,xb):xs@((_,yb):_)) | xb == yb = rmdupSorted xs
| otherwise = x : rmdupSorted xs
rmdupSorted xs = xs -- 0 or 1 elements
rmdup :: Ord a => [a] -> [a]
rmdup = map snd . sort . rmdupSorted . sortBy (comparing snd) . zip [0..]
main = print $ rmdup [1,2,3,4,5,4,6,1,7]
Assuming that the sortBy
function is a stable sort, the rmdup
function will remove all the duplicate occurrences of any element but for the one occurring last. If sortBy
is not stable, then rmdup
will remove all the occurrences but for an unspecified one (i.e., rmdup [1,2,1]
could return [1,2]
instead of [2,1]
.).
Complexity is now O(n log n).
We now need to rewrite the above without library functions, as the OP requested. I will leave this as an exercise to the reader. :-P