I think the O(row * col * light_count * dist) algorithm could be optimized to run in O(row * col * light_count).<p>The idea is, imagine the light is coming from the left, and our height map consists of a single row that looks like (0,5,2,7,1).<p>By using the angle of the light, we can compute from left to right whether the current point should be visible. We only need to store the last point that was also visible since that is the only point that can block us from this light source. For the given example, at point of height 2 we only need to care about the previously visible point of height 5. If 2 isn't visible, 5 remains the "highest" point, if 2 is visible, 2 becomes the "highest" point, there is no danger that 5 will block something beyond two since 2 wasn't blocked. So at each point we only have to check with one previous point, not all.<p>If the light isn't coming from exactly the left side, then we can tranform the image so in such a way that the light is now from the left. This transformation will take O(r * c) time per light.<p>Total complexity: O(transforms + visibilityChecks + mergingResults) = O(l * r * c)