螺旋矩阵第N步坐标求解:现有算法效率优化需求
Hey there! The problem with your current approach is that it simulates every step of the spiral, which becomes way too slow when dealing with enormous grid sizes (like 1e9+) and target values. Instead of looping through each layer, we can use mathematical calculations to directly find which layer the target value is in, then compute its coordinates in constant time O(1) (with binary search for layer detection, it's O(log(gridSize))—negligible even for the largest inputs).
Here's the Breakdown of the Efficient Approach:
Identify the Layer of the Target Value
The spiral matrix can be thought of as concentric square layers. The outermost layer is layer 0, the next inner is layer 1, and so on. The total number of steps up to the end of layerk-1(i.e., all layers outside layerk) can be calculated with the formula:cumulative_steps = 4 * k * (gridSize - k)
We use binary search to find the largestkwhere this cumulative step count is less than the target value. This tells us exactly which layer the target resides in, and the remaining steps within that layer.Find the Starting Coordinates of the Layer
For layerk, the starting position (where the layer begins its spiral) is:start_x = k + 1start_y = k
Each inner layer is shifted 1 row and 1 column inward from the previous layer, which gives us this starting point.
Calculate the Exact Coordinates Using the Offset
Once we have the remaining steps (offset) within the current layer, we determine which side of the square the target is on:- Rightward side: Offset from 1 to
s(side length of the layer) → Coordinates:(start_x, start_y + offset) - Downward side: Offset from
s+1tos + (s-1)→ Coordinates:(start_x + (offset - s), start_y + s) - Leftward side: Offset from
s + (s-1) + 1tos + 2*(s-1)→ Coordinates:(start_x + (s-1), start_y + s - (offset - s - (s-1))) - Upward side: Offset from the remaining steps to
4*(s-1)→ Coordinates:(start_x + (s-1) - (offset - s - 2*(s-1)), start_y)
- Rightward side: Offset from 1 to
Optimized Code Implementation
#include <iostream> #include <sstream> void GetSpiralFinalCoordinates(const unsigned long long gridSize, const unsigned long long finalDestSteps, unsigned long long& x, unsigned long long& y) { if (finalDestSteps == 0) { // Edge case (though input starts at 1 per problem description) x = 1; y = 0; return; } // Binary search to find the layer containing the target unsigned long long low = 0; unsigned long long high = gridSize / 2; unsigned long long best_layer = 0; unsigned long long total_up_to_best = 0; while (low <= high) { unsigned long long mid = low + (high - low) / 2; unsigned long long s_mid = gridSize - 2 * mid; if (s_mid <= 0) { high = mid - 1; continue; } unsigned long long cumulative = 4 * mid * (gridSize - mid); if (cumulative < finalDestSteps) { best_layer = mid; total_up_to_best = cumulative; low = mid + 1; } else { high = mid - 1; } } unsigned long long remaining = finalDestSteps - total_up_to_best; unsigned long long layer = best_layer; unsigned long long s = gridSize - 2 * layer; unsigned long long start_x = layer + 1; unsigned long long start_y = layer; // Determine which side and compute coordinates if (remaining <= s) { // Rightward movement x = start_x; y = start_y + remaining; } else if (remaining <= s + (s - 1)) { // Downward movement remaining -= s; x = start_x + remaining; y = start_y + s; } else if (remaining <= s + 2 * (s - 1)) { // Leftward movement remaining -= s + (s - 1); x = start_x + (s - 1); y = start_y + s - remaining; } else { // Upward movement remaining -= s + 2 * (s - 1); x = start_x + (s - 1) - remaining; y = start_y; } } int main() { unsigned long long x, y; unsigned long long a, b; std::string line; std::getline(std::cin, line); std::istringstream issline(line); issline >> a; issline >> b; GetSpiralFinalCoordinates(a, b, x, y); std::cout << x << " " << y << std::endl; return 0; }
Why This Works for Large Values
This approach avoids any loops that scale with the grid size. Binary search for layer detection takes only ~30 iterations even for gridSize = 1e9, and the rest of the logic is just arithmetic operations. It handles ultra-large inputs (like gridSize=1073741824 and target=1152921504603393520) easily within the 1-second time limit.
Testing the Example
For gridSize=8 and finalDestSteps=53:
- Binary search finds that cumulative steps up to layer 1 is 48, so remaining steps = 53-48=5
- Layer 2 has a side length of 4. The remaining 5 steps fall in the downward side of the layer
- Calculated coordinates:
(3+1, 2+4) = (4,6), which matches manual calculation of the spiral path.
内容的提问来源于stack exchange,提问作者Vinícius

