You're takingOne way is to the sequence 0,1,2,3,4,5 or ...(N-1) and using these as row coords in a sparse-matrix (CSR) representation:
from scipy.sparse import csr_matrix
N = 6
csr_matrix(([1]*6, ([0,3,1,4,2,5], [0,1,2,3,4,5] ))).toarray()
array([[1, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 1, 0],
[0, 1, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 1]], dtype=int64)
and for general N:
csr_matrix(([1]*N, ([0,3,1,4,2,5], list(range(N)) ))).toarray()
array([[1, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 1, 0],
[0, 1, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 1]], dtype=int64)
and a roundrobin iterator to generate the low/hi values:
from itertools import chain, zip_longest, cycle
# If you know N is even, you can get away with this...
N = 6
[x for its in zip(range(N//2), range(N//2, N)) for x in its]
# [0, 3, 1, 4, 2, 5]
# But in the general case, N could be odd, and you need to handle one of the iterators being exhausted first and yielding None...
N = 7
[x for its in zip_longest(range(N//2), range(N//2, N)) for x in its if x is not None]
# [0, 3, 1, 4, 2, 5, 6]
(It turned out writing that roundrobin iterator was a world of pain. Could be less grief to use bitwise arithmetic, or imperative code like the other answers.)