I didn't actually test your script but it should theoretically find the largest and smallest. However not the 2nd largest and 2nd smallest as you need.
Also your random number generator is slightly flawed. It has the possibility of generating a number all the way up to 1099 which is not three digit.
Here is my stab at your task though:
#!/usr/bin/env bash
for ((i=0;i<10;i++)); do
numbers+=($(((RANDOM%900)+100)))
done
largest=0
oldlargest=0
smallest=1000
oldsmallest=1000
for n in "${numbers[@]}"; do
if [[ $n -gt $largest ]]; then
oldlargest=$largest
largest=$n
elif [[ $n -gt $oldlargest && $n -lt $largest ]]; then
oldlargest=$n
fi
if [[ $n -lt $smallest ]]; then
oldsmallest=$smallest
smallest=$n
elif [[ $n -lt $oldsmallest && $n -gt $smallest ]]; then
oldsmallest=$n
fi
done
printf 'Second largest is: %d\nSecond smallest is: %d\n' "$oldlargest" "$oldsmallest"
I'm sure someone could probably figure out a more elegant way to do it but this will keep track of both the largest and smallest numbers so far, and the second largest and smallest numbers so far. Leaving us with both values at the end.
sortrather than iterating with afor do ... doneshell loop is the faster and more efficient way to get the result. It depends of course on the size of your array.