My twopence to this is that there is an opportunity (for performance reasons) to bail out of the algorithm as soon as the conditions are detected (indicating therefore the pre- instead of post-increment operator), rather than poll the whole array willy-nilly, reducing the test then to this one-liner:
( ++$hash{$_} < 3 or die "too many matched elements" ) for (@array);