With these constraints, there are quite a few interesting techniques, for example in Scheme you can apply append:
(apply append list-of-lists)
or in Python you can use reduce with add operator: reduce(op.add, list_of_lists) # op == operator module
And anyway, even if it's not the constrained version, the solution is indeed trivial, for example in Erlang: flatten(L) -> flatten(L, []).
flatten([], Acc) -> Acc;
flatten([[] | T], Acc) -> flatten(T, Acc);
flatten([[_|_]=H | T], Acc) -> flatten(T, Acc ++ H);
flatten([X | T], Acc) -> flatten(T, Acc ++ [X]).
(please don't mind the inefficient use of ++, it's a toy example...)It can get a bit more complex in a statically typed language, especially if you want to have static guarantees (no down-casting from Object), but it's still doable in a couple of minutes...
...is what this post - and discussion - is not about.
It's trivial once you get it, of course. But it's also true that it's almost impossible to figure it out on your own during a stressful interview if you didn't get it beforehand. It's so easy to forget that. We all once struggled with some concepts, and we all went through many discoveries of facts, techniques, and skills we didn't know existed, much less that we needed them.
What I want to say is that the beginners who fail to answer this question are not bad, they are just beginners. It's ok to reject them right now, but it's not ok to post an article suggesting that "programmers find it hard to solve trivial problems even with my help". It's not programmers, but beginner programmers; it's not trivial problem, just relatively widely known one; and it may well be the help was insufficient.