Hmm, the only problem with this is that my optimised routine gives the wrong answer. The bug is that, if the largest element is at the beginning or the smallest is at the end of the list, my test will skip it when it shouldn't. So the condition really needs to be something like:
my ($n, $first, $last) = ($#$copy, @$copy[0,-1]);
if ( ( $first == $n+1 || $first != max(@$copy[0..($first -
+ 1)]) )
&& ( $last == 1 || $last != min(@$copy[($last - 1)..$n])
Now it's a little faster than the original on my laptop, and a little slower on the Linux box.