newsgroups-index (beta)

Current group: comp.programming

array Puzzle (spoiler)

array Puzzle (spoiler)  
Paul Hsieh
From:Paul Hsieh
Subject:array Puzzle (spoiler)
Date:23 Jan 2005 08:42:26 -0800
Alf P. Steinbach wrote:
> * dtmoore:
> > Alf P. Steinbach wrote:
> > > * dtmoore:
> > > > Alf P. Steinbach wrote:
> > > > > * puzzlecracker:
> > > > > > Given an array of size n and populated with consecutive
> > > > > > integers from 1 to n i.e. [1, 2...n-1, n] in random order.
> > > > > > Two integers are removed, meaning zero is placed in their
> > > > > > places. Give O (n) efficient algorithm to find them?
> > > >
> > > > [Snip}
> > > >
> > > > > As a programming puzzle it's a bit more interesting (but
> > > > > still novice-level) if memory usage is restricted to O(1)
> > > > > except the original array itself, and for that I'm cross-
> > > > > posting this to [comp.programming], with follow-up there.
> > > >
> > > > Ok, I can see how to solve the puzzle with an algorithm that is
> > > > O(n) in time and O(1) in memory, but only when two values are
> > > > removed. Is there to solve it when more than two values are
> > > > zero'd out and still use O(1) memory?
> > >
> > > Well I don't know.
> > >
> > > I assume your solution involves a root?
> >
> > Actually no, I guess it is simpler than that. Since the (before
> > cross-posting) OP's homework is probably past due by now , I
> > will lay out the algorithm here.
> >
> > The key is that the integers in the input array are sequential,
> > even if they are shuffled. Thus the sum, S, of the complete,
> > original array is known: S=(n+1)*n/2. So, one can compute the
> > sum, s, of the input array (with the zeros) and subtract it from
> > the expected value to recover the sum of the missing elements
> > (a + b = S - s = c).
> >
> > Since a and b are unique, one of them must be smaller than c/2.
> > So, we again iterate through the array, this time summing only
> > those elements which are less than c/2, and again subtract from
> > the expected sum: (k+1)*k/2, where k is the largest integer less
> > than c/2.
> >
> > This will recover the value of the smallest of the two "missing"
> > integers, and of course the second comes from a + b = c.

Very nice! A complete solution that can be implemented
straightforwardly without numerical issues!

> > How would you do it using roots?
>
> It was much more brute force, computing both the sum and the product
> of the numbers (the latter quantity would tend to be, uh, laaarge),
>
> x + y = s
> x * y = p
>
> where s = n*(n+1)/2-sumOfArray and p = n!/productOfArray, yields
> simple quadratic equation.

Actually, using roots is not necessary, since you can iterate through
the possible x and y (again, its O(n)) and just check to see if its
matches the product. The real problem with that solution is computing
n!

But similarly, the following can be computed:

x + y = s
x^2 + y^2 = q

And this solves to a unique pair of x and y as well (exercise to the
reader.) The advantage of this is that it can be computed exactly
with a bignum library that only requires triple-wide integers. Also
there is a chance that computing q (mod k) (instead of q which can
overflow), for some small k might still work, and can be computed as
well. The point is that there is almost surely a fixed sequence of
k's (probably some appropriately chosen primes or something like that)
for which you can compute these q's and again do the forward for loop.

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/
   

Copyright © 2006 newsgroups-index   -   All rights reserved   -   Impressum