O (min (n, m)) is impossible: take two lists [x; x; ...; x; y] and [x; x; ...; x; z]. You must look at both lists to the end to compare y and z.
Even O (n + m) is impossible. accept [1,1, ..., 1] - n times and also [1,1, ..., 1] - m times Then the resulting list should have n * m elements. You need at least O (nm) (correctly Omega (nm)) to create such a list.
Without a Cartesian product (a simple merger) it is quite simple. Ocaml code (I don't know, F #, should be close enough, compiled, but not tested):
let rec merge ab = match (a,b) with ([], xs) -> xs | (xs, []) -> xs | (x::xs, y::ys) -> if x <= y then x::(merge xs (y::ys)) else y::(merge (x::xs) (y::ys));;
(Edit: I'm late)
So your code in O (nm) is the best in the worst case. However, IIUIC always performs n * m operations, which is not optimal.
My approach will be
1) write a function
group: 'list → (' a * int) list
which counts the number of identical elements:
group [1,1,1,1,1,2,2,3] == [(1,5); (2.2); (3.1)]
2) use it to combine both lists using the same code as before (there you can multiply these coefficients)
3) write a function
ungroup: ('a * int) list →' list
and make these three.
This has complexity O (n + m + x), where x is the length of the resulting list. This is the maximum possible value until constant.
Edit: here you are:
let group x = let rec group2 lm = match l with | [] -> [] | a1::a2::r when a1 == a2 -> group2 (a2::r) (m+1) | x::r -> (x, m+1)::(group2 r 0) in group2 x 0;; let rec merge ab = match (a,b) with ([], xs) -> [] | (xs, []) -> [] | ((x, xm)::xs, (y, ym)::ys) -> if x == y then (x, xm*ym)::(merge xs ys) else if x < y then merge xs ((y, ym)::ys) else merge ((x, xm)::xs) ys;; let rec ungroup a = match a with [] -> [] | (x, 0)::l -> ungroup l | (x, m)::l -> x::(ungroup ((x,m-1)::l));; let crossjoin xy = ungroup (merge (group x) (group y));;