The answer based on Linear Programming (LP) is is clear and easy to implement, and can be used generally for a much broader class of intersection problems. However, we can gain a bit of efficiency in some cases by exploiting the geometry of this problem directly, as described below.
Method 1: direct test for intersection
This is fast for low dimensions e.g. N=4 or 5, but scales poorly for large N.
Consider projecting a unit $N$-cube centered at $\mathbf p \in \mathbb R^N$ onto a plane centered at the origin and defined by the vectors $\mathbf u, \mathbf v \in \mathbb R^N$. (The more general problem of checking for the intersection of a $N$-cube and a plane can be reduced to this with the right choice of coordinates.)
The plane defines a 2D $(s,t)$ subspace of $N$-D space, with basis $A = (\mathbf u, \mathbf v)$
$$
\mathbf x = A \begin{bmatrix} s\\t \end{bmatrix}
$$
We can project the problem onto the null space of the plane, $A^\perp$. This sends every point on the plane to zero. The problem then reduces to testing whether the $N{-}2$ projection of the hypercube contains the origin.
Projecting the $N$-cube down to $N{-}2$ dimensions creates a polytope that can be expressed as the union of all $N{-}2$ faces of the original $N$-cube. If any of these faces contains the origin, then the original hypercube intersects the plane.
E.g. projecting a 4-cube down to 2D yields a collection of 2D rhombi, one for each 2D faces of the 3D facets of the 4-cube. If any of these rhombi contain the origin, then we know the 2D plane intersects the 4-cube in our original problem.
One way to check if a $N{-}2$ rhombus contains the origin is to change to a basis where the rhombus is a cube $[0,1]^{N-2}$, and test if this cube contains the origin. Do this by selecting one vertex of the rhombus, and all the points it immediately connects to, as your basis set.
(When checking all sub-facets, you can stop as soon as you've found a single sub-facet that contains the target point)
This seems inefficient, but is faster than using e.g. Python's built-in linear programming solvers for $N{=}4$. It scales badly to higher dimensions, however.
There might be a more elegant solution if one could exploit symmetries and eliminate redundant computations.
Method 2: $\mathcal O[ N \log(N) ]$ via Preparata and Muller's algorithm (or something like it)
First, transform the problem into a set of $2N$ linear inequality constraints. Each constraint defines a half-plane. The plane intersects the hypercube if the intersection of these half-planes is nonempty.
So far, this is identical to the linear programming approach. But, as it turns out, there are specific algorithms for testing whether the intersection of $n=2N$ half-planes is nonempty. For example, here is an approach by Preparata and Muller for solving the intersection of $n$ half-spaces with $n\log(n)$ time complexity. There are other variants (e.g. Wu, Ji, and Chen), but they all have the same complexity.
These lecture notes by Dave Mount are especially useful for understanding the geometry underlying these algorithms. These notes show how to construct the (convex) intersection set as the intersection of a (convex) upper and lower envelope.
The basic pseudocode is:
- First, identify any vertical bounding lines. These demarcate spans of the $s$ axis of the plane. Their intersection $s\in[s_0,s_1]$ defines the bounds for a search procedure (below).
- Split the remaining lines into those that bound the half-plane from below, and those that bound the half plane from above, where "below" and "above" are defined in terms of the $t$ coordinate of the plane.
- These two sets of lines define and upper and lower feasibility regions, which are convex. The boundary of these regions can be interpreted as curves $t_l(s)$ and $t_u(s)$
- We can test if the the intersection between the upper/lower feasibility regions is nonempty by finding the minimum of $t(s) = t_l(s)-t_u(s)$ on $s\in[s_0,s_1]$
- If any $\exists s\in[s_0,s_1]\text{ s.t. } t(s)<0 $, then the plane intersects the hypercube.
- This can be checked via binary search, looking for the point where $t(s)$ changes sign, and stopping early if any point satisfying all the constraints is found.