The desired behavior of your findHole
function isn't 100% clear to me, but the following code snippet will give you an array that has all the "missing" indexes.
$ar = array( 1=>'foo', 2=>'bar', 5=>'foobar', 8=>'barfoo' );
$keys = array_keys($ar);
$missing_indexes = array_diff(range(0,max($keys)), $keys);
print_r($missing_indexes);
Depending on your use case this may or may not be less efficient. It's using multiple function calls and arrays are passed around by value by default, but those functions are operating at native code speeds, while solutions using loops are going to be running at PHP speed.
Use case, benchmark, etc.