This answer complements @CedronDawg's answer which introduced this family of eigenvectors. More specifically, this answer presents three algorithms and a hybrid algorithm for generating for a given length $N$ the unique (except for normalization) non-negative eigenvector of discrete Fourier transform (DFT) with the maximal number of consecutive zeros. This is the normal DFT with no half-sample shifts in time or frequency.
Iterative algorithm, $\sim O\big(\exp(N)\big)$ time
Here is an iterative numerical algorithm to find the eigenvectors satisfying the said constraints. The algorithm principle is to repeat enforcing the defining constraints in each domain and averaging the results. It is similar to Projection Onto Convex Sets (POCS) algorithms. In Octave:
function retval = constrain(x, N)
zerocount = N-floor((N+2)/4)*2-1;
if (zerocount > 0)
firstzero = floor((N+10)/4);
x(firstzero:firstzero+zerocount-1) = 0;
endif
x = abs(x);
retval = x / x(1);
endfunction
function retval = geteig_iterative(N, precision = 0, x = ones(1, N))
x = constrain(x, N);
good = x;
X = fft(x)/sqrt(N);
error = sumsq(x-X);
iter = 0;
while (max(abs(X-x)) > precision)
lasterror = error;
X = constrain(X, N);
temp = X;
x = (x + X)/2;
X = fft(x)/sqrt(N);
error = sumsq(x-X);
iter++;
if (error >= lasterror)
break;
endif
good = temp;
endwhile
printf("Iterations: %d\n", iter);
retval = good;
endfunction
N = 21; x = geteig_iterative(N); plot([0:N-1], x, "x", [0:N-1], real(fft(x)/sqrt(N)), "+");
The algorithm can be given a starting point vector. Otherwise it starts with a vector of ones. The parameter precision
defines the desired precision as the maximum absolute difference between the calculated eigenvector and its DFT, for example precision = 0.000000000001
, or the default precision = 0
to halt the algorithm when an iteration no longer improves the solution.
The variables firstzero
and zerocount
determine the location and the number of zeros. Their formulas are in the realm of empirical mathematics, but were also guided by experience from symbolically solving the problem for some small values of $N$, and partially by testing whether random-vector initialization changes the results or if zerocount
can still be increased.
For $N = 21$, the result is obtained in 2605
iterations:

Figure 1. The output of the iterative algorithm (✕) and its DFT (+), for $N = 21$.
Unfortunately, the algorithm needs a number of iterations that is exponentially proportional to $N$, so it is not useful for large $N$, and it also fails to converge for some not that large values of $N$ like $18$ and $22$:

Figure 2. Number of iterations needed for precision = 0.000000000001
, as function of $N$.
Despite the algorithm's shortcomings at large $N$, the results at smaller $N$ are useful, showing clear structure suitable for algorithmic construction. The structure is best viewed by looking at the frequency-domain and other z-plane zeros of the non-zero portion of the unwrapped eigenvectors, in Octave by zplane(nonzeros(fftshift(geteig_iterative(N)))');
:

Figure 3. $z$-plane zeros (◯) of the non-negative subsequences of the unwrapped eigenvectors. Poles (✕) can be ignored in these Z-plane plots. Not too easy to see, but there is a double zero at $z = -1$ when $\operatorname{mod}(N, 4) \in \{0, 2\}$. $N < 3$ were not included, because it was ambiguous how to split the unwrapped eigenvector to obtain the non-zero subsequence.
The analysis shows a $4$-periodic pattern in the zero distributions, as function of $N$. Double zeros at $z = -1$ can be seen when $\operatorname{mod}(N, 4) \in \{0, 2\}$. The two first columns with $\operatorname{mod}(N, 4) \in \{0, 1\}$ show a regular spacing of the zeros on the unit circle, representing real zeros in frequency domain that correspond to the frequencies of the DFT bins. For $\operatorname{mod}(N, 4) \in \{2, 3\}$, there are two necessary but somewhat arbitrarily placed real zeros, one inside and one outside the unit circle, with their value uniquely defined for a given $N$, as confirmed by testing with random-vector initializations. Symmetry constraints require that the additional pair of zeros is a reciprocal pair, reducing the number of unknowns to just one, which is an easy problem to solve numerically, as will be done in the fast algorithms in the following sections.
The simplicity of the pattern of zeros seen with $\operatorname{mod}(N, 4) = 1$ is attractive. It may be attractive enough to choose a time and/or frequency-shifted variant of DFT depending on $\operatorname{mod}(N, 4)$, to ensure the same simplicity for all $N$. However, it may be important to include a zero-frequency bin, and as the question was about the usual kind of DFT, I will stick to that for this answer.
Fast convolutional algorithm, $O\big(N\log^2(N)\big)$ time
@CedronDawg's approach was to construct the eigenvectors as products of real-valued vectors that each created at most two zeros. Here is presented a fast algorithm that uses a similar principle, but instead of multiplying such vectors one by one, it takes a divide-and-conquer approach. In this convolutional algorithm, frequency-domain zeros are created by time-domain convolution. Convolution by conv
is accelerated by fast Fourier transform (FFT), which gives a total time complexity of $O\big(N\log^2(N)\big)$.
The main work in the algorithm is to create a long train of frequency-domain zeros. Such work is split to creating and combining a pair of half-length trains, recursively, until the length of the train to create is only 3 or less. The time-domain sequence corresponding to such a short train can be expressed simply and directly. For odd-length trains the middle zero is created separately. Instead of creating half-trains individually, they are cloned and shifted to the appropriate place by complex sinusoid modulation. This way the recursions do not create a call tree but only a short call chain of length $O\log(N)$. In Octave:
function retval = getzeros(N, M)
if (M == 1)
retval = [1, -1];
elseif (M == 2)
retval = [1, -2*cos(pi/N), 1];
elseif (M == 3)
retval = [1, -1 - 2*cos(2*pi/N), 1 + 2*cos(2*pi/N), -1];
elseif (rem(M, 2) == 0)
half = getzeros(N, M/2);
modulator = exp(i*[((0:M/2)-M/4)*2*pi*M/4/N]);
retval = real(conv(conj(modulator).*half, modulator.*half));
else
half = getzeros(N, (M-1)/2);
modulator = exp(i*[((0:(M-1)/2)-(M-1)/4)*2*pi*(M+1)/4/N]);
retval = conv(real(conv(conj(modulator).*half, modulator.*half)), getzeros(N, 1));
endif
endfunction
#[h, w] = freqz(getzeros(10, 4), [], 500); plot(abs(h));
function retval = geteig_convolutional(N)
M = N-floor((N+2)/4)*2-1;
x = getzeros(N, M);
if (rem(M, 2) == 1)
x = conv(x, getzeros(N, 1));
endif
x .*= (-1).^[0:length(x)-1];
mid = (length(x) + 1)/2;
if (rem(N, 4) == 2 || rem(N, 4) == 3)
s = sum(x)/sqrt(N);
x = conv(x, [1, 2*(s - x(mid + 1))/(x(mid) - s), 1]);
endif
retval = circshift(horzcat(x/x(mid), zeros(1, N-length(x))), (rem(N,4) < 2)-mid);
endfunction
N = 512; x = geteig_convolutional(N); plot([0:N-1], x, "x", [0:N-1], real(fft(x)/sqrt(N)), "+");
plot([0:N-1], x - real(fft(x)/sqrt(N)), "x");
This plots:

Figure 4. The output of the fast convolutional algorithm (✕) and its DFT (+), for $N = 512$.

Figure 5. The difference between the output of the fast convolutional algorithm and its DFT, for $N = 512$.
The convolutional algorithm begins to explode with numerical error for large values of $N$ roughly $N > 750$, I guess partially because of back-and-forth FFT – inverse FFT (IFFT). The multiplicative algorithm presented in the next section will be much more stable.
The code includes creating the reciprocal zeros needed for $\operatorname{mod}(N, 4) \in \{2, 3\}$ as seen in Fig. 3. For that, the value for the variable $a$ in convolution by $[1, a, 1]$, which creates the reciprocal zeros, was solved from an equation $x[-1] + a\,x[0] + x[1] = X[0] + a\,X[0] + X[0]$. The equation requires that after convolution, the value at time domain origin (represented by the left side of the equation) equals the value at frequency domain origin (right side), with $x$ and $X$ representing the nascent eigenvector and its DFT before the convolution.
Fast multiplicative algorithm, $O\big(N\log(N)\big)$ time
Here is the multiplicative version of the fast algorithm. It creates zeros in the same domain in which it constructs the eigenvector. Intermediate results are stored in logarithmic scale to accommodate for the large dynamic range of the numbers. In Octave:
function retval = get_log2_zeros_multiplicative(N, M)
k = [0:N-1];
if (M == 1)
x = log2(abs(sin(pi*k/N)));
elseif (M == 2)
x = log2(abs(cos(pi/N) - cos(2*pi*k/N + pi/N)));
elseif (M == 3)
x = log2(abs(sin(pi*k/N).*(2*cos(2*pi/N) + 1) - sin(3*pi*k/N)));
elseif (rem(M, 4) == 0)
half = get_log2_zeros_multiplicative(N, M/2);
x = circshift(half, M/4) + circshift(half, -M/4);
elseif (rem(M, 4) == 1)
half = get_log2_zeros_multiplicative(N, (M-1)/2);
x = circshift(half, (M-1)/4+1) + circshift(half, -(M-1)/4) + get_log2_zeros_multiplicative(N, 1);
elseif (rem(M, 4) == 2)
half = get_log2_zeros_multiplicative(N, M/2);
x = circshift(half, (M-2)/4) + circshift(half, -((M-2)/4+1));
else
half = get_log2_zeros_multiplicative(N, (M-1)/2);
x = circshift(half, (M-3)/4+1) + circshift(half, -((M-3)/4+1)) + get_log2_zeros_multiplicative(N, 1);
endif
retval = x - round(max(x));
endfunction
function retval = geteig_multiplicative(N)
M = N-floor((N+2)/4)*2-1;
x = get_log2_zeros_multiplicative(N, M);
if (rem(M, 2) == 1)
x += get_log2_zeros_multiplicative(N, 1);
endif
x = ifftshift(2.^x);
firstzero = floor((N+10)/4);
x(firstzero:firstzero+M-1) = 0;
if (rem(N, 4) == 2 || rem(N, 4) == 3)
x0 = sum(x)/sqrt(N);
x1 = sum(x.*cos(2*pi*[0:N-1]/N))/sqrt(N);
s = x(1);
x .*= 2*cos(2*pi*[0:N-1]/N) + 2*(s - x1)/(x0 - s);
endif
retval = x/x(1);
endfunction
N = 512; x = geteig_multiplicative(N); plot([0:N-1], x - real(fft(x)/sqrt(N)), "x");
At $N = 512$, the error from the fast multiplicative algorithm is very low:

Figure 6. The difference between the output of the fast multiplicative algorithm and its DFT, for $N = 512$.
For $N = 65536$, the absolute difference (not shown, analogous to Fig. 6) between the eigenvector calculated using the fast multiplicative algorithm and its DFT will be under 1e-12
.
Hybrid multiplicative-iterative algorithm, $O\big(\log(N)N\big)$ time
The output of the multiplicative algorithm can still be refined using the iterative algorithm. In Octave:
function retval = geteig_hybrid(N)
if (N < 4)
retval = geteig_iterative(N, 0);
else
retval = geteig_iterative(N, 0, geteig_multiplicative(N));
endif
endfunction
N = 512; x = geteig_hybrid(N); plot([0:N-1], x - real(fft(x))/sqrt(N), "x");

Figure 7. The difference between the output of the fast hybrid multiplicative-iterative algorithm and its DFT, for $N = 512$, calculated in 9
refining iterations.
Using the iterative refinement, for $N = 65536$, the absolute difference (not shown, analogous to Fig. 7), between the eigenvector calculated using the fast multiplicative algorithm and its DFT, can be reduced from under 1e-12
to under 3e-16
in 23
iterations.
Conclusion
The multiplicative algorithm geteig_multiplicative(N)
and the hybrid multiplicative-iterative algorithm geteig_hybrid(N)
are very fast even for very large $N$, and are the recommended algorithms to use for generating these eigenvectors. The iterative refinement by the hybrid algorithm will be blind to any error due to Octave's FFT being done in double-precision floating point, which may in some applications give more error than the multiplicative algorithm which it uses to calculate the starting point of its iterations. The output of the multiplicative algorithm is guaranteed to be unimodal (Fig. 8), in the unwrapped sense, unlike the output of the hybrid algorithm.

Figure 8. Base-10 logarithm of the unwrapped eigenvector calculated by the multiplicative algorithm (thick blue line) and its best-fit quadratic trendline (thin black line), for $N = 65536$. The logarithm of a Gaussian function is quadratic. The close match demonstrates that as $N\to\infty$, this type of an eigenvector approaches a Gaussian function. The first zeros would be in a plot like this at times $\pm$ floor((N+6)/4)
, for any $N$, in the current case at $\pm 16385$, meaning that both the Gaussian and the eigenvector take a dive to extremely small values already a long way away from the zeros.