Last Updated: April 2, 2026
This is a simulation problem that models how Candy Crush works behind the scenes. We need to repeatedly perform two operations until the board stabilizes: first, find and mark all groups of three or more identical candies in a row (horizontally or vertically), then crush them all at once and let gravity pull the remaining candies downward.
The tricky part is that crushing must happen simultaneously. You can't crush one group, drop, then look for the next group in the same iteration. All crushable candies in a given round must be identified before any of them are removed. After removal and gravity, you check again. The process repeats until a full scan finds nothing to crush.
The key observation is that this problem breaks down into three clean sub-problems that we loop over: mark (find all crushable candies), crush (set them to zero), and drop (apply gravity column by column). Once a full mark phase finds zero candidates, we're done.
3 <= m, n <= 50 → The board is small, at most 2,500 cells. Even O(m^2 * n^2) per iteration would be fast enough. Efficiency isn't a concern here, clarity and correctness are.1 <= board[i][j] <= 2000 → Candy values are always positive. This means we can use negative values as markers without conflicting with actual candy types.The most straightforward approach: use a separate boolean matrix to track which cells need to be crushed. Scan every cell to see if it's part of a horizontal or vertical run of three or more identical candies. Mark all such cells in the boolean matrix, crush them (set to 0), apply gravity, and repeat.
This is the approach you'd naturally come up with if you just followed the problem description step by step. It directly models the game loop: find matches, remove them, drop, check again.
crush of the same size as the board, initialized to all false.true in the crush matrix.true, set board[i][j] = 0.This approach works correctly but allocates a fresh boolean matrix every iteration. Since all candy values are positive, what if we used the sign of each value as a built-in flag to mark cells for crushing?
Since all candy values are positive integers, we can negate a value to mark it for crushing while still being able to read its candy type via abs(). This eliminates the need for a separate boolean matrix entirely.
The algorithm follows the same three-phase loop (mark, crush, drop), but the marking phase now flips values to negative instead of writing to a separate array. When checking if adjacent cells match, we compare absolute values so that already-marked cells still participate in matching. After marking, any cell with a negative value gets set to 0, and gravity drops the rest down.
The negation trick works because it's reversible and non-destructive. When we negate board[i][j], we can still recover the candy type with abs(board[i][j]). This means cells that have already been marked can still participate in matching, which is critical. Consider a row like [3, 3, 3, 3]. When we check positions 0-2, we negate all three. When we then check positions 1-3, position 1 is already negative, but abs(-3) == abs(3), so the match is correctly detected and position 3 gets negated too. All four cells end up marked.
abs(board[i][j]) == abs(board[i][j+1]) == abs(board[i][j+2]) and the value is non-zero, negate all three cells (if not already negative).board[i][j], board[i+1][j], board[i+2][j].