Es bueno saber que aún existen programadores que no desean desperdiciar memoria(espacio) obscenamente. Sin embargo también es bueno evitar desperdiciar tiempo (de proceso) o hacer el programa innecesariamente complejo.
Un byte por número me parece el punto de equilibrio ideal.
Puedes ahorrar más espacio usando algoritmos de compresión, por ejemplo la biblioteca 7z. Pero esto sólo tiene sentido si tus datos ocupan varios MBytes, no vale la pena por 100 Bytes.
De hecho para lograr el mínimo teórico tendrías que lograr comprimir esa información hasta alcanzar su estado máximo de entropía.
Una forma simple sería calcular las diferencias (recodificación para hacer más evidente correlaciones en la información a comprimir) y luego aplicar un codificador de entropía como este:
http://en.wikipedia.org/wiki/Huffman_coding.
Datos originales : 1 , 2 , 4, 5, 7, 9, 12, 15, 16, 20
Diferencias(comenzando con 0): 1, 1, 2, 1, 2, 2, 3, 3, 1, 4
Si sólo exitieran 4 valores para las diferencias (1, 2, 3 y 4) el algoritmo huffman codificaría dichos números en 2 bits, ahorrando 75 bytes para ese caso muy particular. (En general asigna códigos de tamaño variable más chicos a elementos más frecuentes y códigos de tamaño variable más largos a los menos frecuentes).
Sin embargo también es necesario guardar la tabla de traducción de nuevos códigos de 2 bits a sus originales de 8 bits (o el árbol de codificación que a veces ocupa menos espacio). También es necesario espacio para guardar la implementación del algoritmo necesario para descomprimir la información. Asi que por todo lo anterior no es práctico comprimir una cantidad de información tan pequeña, a menos que sea por fines puramente académicos.