Inicialize uma matriz de 1001 números inteiros com os valores 0-1000 e defina uma variável, max, para o índice máximo atual da matriz (começando com 1000). Escolha um número aleatório, r, entre 0 e max, troque o número na posição r pelo número na posição max e retorne o número agora na posição max. Reduza no máximo 1 e continue. Quando max for 0, defina max novamente para o tamanho da matriz - 1 e inicie novamente sem a necessidade de reinicializar a matriz.
Atualização:
Embora eu tenha inventado esse método sozinho quando respondi à pergunta, depois de algumas pesquisas, percebo que essa é uma versão modificada de Fisher-Yates conhecida como Durstenfeld-Fisher-Yates ou Knuth-Fisher-Yates. Como a descrição pode ser um pouco difícil de seguir, forneci um exemplo abaixo (usando 11 elementos em vez de 1001):
A matriz começa com 11 elementos inicializados na matriz [n] = n, max começa com 10:
+--+--+--+--+--+--+--+--+--+--+--+
| 0| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|
+--+--+--+--+--+--+--+--+--+--+--+
^
max
A cada iteração, um número aleatório r é selecionado entre 0 e max, a matriz [r] e a matriz [max] são trocadas, a nova matriz [max] é retornada e max é decrementado:
max = 10, r = 3
+--------------------+
v v
+--+--+--+--+--+--+--+--+--+--+--+
| 0| 1| 2|10| 4| 5| 6| 7| 8| 9| 3|
+--+--+--+--+--+--+--+--+--+--+--+
max = 9, r = 7
+-----+
v v
+--+--+--+--+--+--+--+--+--+--+--+
| 0| 1| 2|10| 4| 5| 6| 9| 8| 7: 3|
+--+--+--+--+--+--+--+--+--+--+--+
max = 8, r = 1
+--------------------+
v v
+--+--+--+--+--+--+--+--+--+--+--+
| 0| 8| 2|10| 4| 5| 6| 9| 1: 7| 3|
+--+--+--+--+--+--+--+--+--+--+--+
max = 7, r = 5
+-----+
v v
+--+--+--+--+--+--+--+--+--+--+--+
| 0| 8| 2|10| 4| 9| 6| 5: 1| 7| 3|
+--+--+--+--+--+--+--+--+--+--+--+
...
Após 11 iterações, todos os números na matriz foram selecionados, max == 0, e os elementos da matriz são embaralhados:
+--+--+--+--+--+--+--+--+--+--+--+
| 4|10| 8| 6| 2| 0| 9| 5| 1| 7| 3|
+--+--+--+--+--+--+--+--+--+--+--+
Nesse ponto, o máximo pode ser redefinido para 10 e o processo pode continuar.