That's very neat. I'm not sure why it'd be a problem with overflow though. Just add the numbers mod m, where m is greater than the largest number, e.g. 2^32. For the first do sum(array) - sum(1..n-1), for the second do sum(1..n+1) - sum(array). Since e.g. the integers modulu n under addition is an abelian group, cancellation works as expected.
A less elegant, but completely different way that I thought of first would be to "attempt" a sort of count-sort of the numbers. When doing this for the first problem, at some point you're going to find the duplicate element. In Python (for 0..n-1):
def find_extra(a):
for i in range(len(a)):
while a[i] != i:
j = a[i]
a[i], a[j] = a[j], a[i] # swap
if a[i] < i:
return a[i]
The second problem could be sledge-hammered into a similar solution:
def find_missing(a):
lastp = len(a)
for i in range(len(a)):
while a[i] != i:
j = a[i]
if a[i] == len(a):
lastp = i
break
a[i], a[j] = a[j], a[i] # swap
return lastp