The "Moving Stones Until Consecutive" problem involves three stones placed at distinct positions on a number line. You are given three integers, a
, b
, and c
, representing the positions of the stones. In each move, you can pick up the stone at the leftmost or rightmost position and move it to any position between the other two stones, as long as the stone does not land on a position already occupied by another stone.
Your goal is to find two things:
x
, x+1
, and x+2
for some integer x
).Constraints:
a
, b
, c
are distinct integers.At first glance, the problem seems to require simulating all possible moves, but since there are only three stones, we can reason about the possible configurations directly. The main challenge is to minimize and maximize the number of moves needed to make the stones consecutive.
For the minimum moves, we want to bring the stones together as quickly as possible. If two stones are already next to each other (i.e., the difference between their positions is 1), only one move is needed. If all stones are already consecutive, no moves are needed. If there is a gap of 2, we can also solve it in one move. Otherwise, two moves are required.
For the maximum moves, we always move the stone from one end towards the other, but only by one position at a time (never skipping over the middle stone), until all stones are consecutive. The maximum number of moves is simply the sum of the gaps between the stones, minus 2 (since the last move will bring the stones together).
Here’s how we can solve the problem step by step:
a < b < c
. This makes it easy to calculate the gaps between the stones.
left_gap = b - a
and right_gap = c - b
.
left_gap - 1 + right_gap - 1
, since we can only move the end stones one step at a time.We use simple arithmetic and conditional logic instead of brute-force simulation, making the solution efficient and easy to understand.
Let's walk through a sample input: a = 1
, b = 2
, c = 5
.
left_gap = 2 - 1 = 1
, right_gap = 5 - 2 = 3
So, the minimum moves are 1, and the maximum moves are 2.
Brute-force Approach:
The optimized approach is constant time and space because the number of stones is always three.
The "Moving Stones Until Consecutive" problem is elegantly solved by sorting the stones, calculating the gaps, and applying simple conditional logic to determine the minimum and maximum moves. The key insight is recognizing that, with only three stones, all possible configurations can be reasoned about directly without simulation. This leads to a constant-time solution that is both efficient and easy to implement.
def numMovesStones(a: int, b: int, c: int):
x, y, z = sorted([a, b, c])
left_gap = y - x
right_gap = z - y
# Minimum moves
if left_gap == 1 and right_gap == 1:
min_moves = 0
elif left_gap <= 2 or right_gap <= 2:
min_moves = 1
else:
min_moves = 2
# Maximum moves
max_moves = (left_gap - 1) + (right_gap - 1)
return [min_moves, max_moves]
#include <vector>
#include <algorithm>
using namespace std;
vector<int> numMovesStones(int a, int b, int c) {
int x = min(a, min(b, c));
int z = max(a, max(b, c));
int y = a + b + c - x - z;
int left_gap = y - x;
int right_gap = z - y;
int min_moves, max_moves;
if (left_gap == 1 && right_gap == 1) {
min_moves = 0;
} else if (left_gap <= 2 || right_gap <= 2) {
min_moves = 1;
} else {
min_moves = 2;
}
max_moves = (left_gap - 1) + (right_gap - 1);
return {min_moves, max_moves};
}
import java.util.Arrays;
class Solution {
public int[] numMovesStones(int a, int b, int c) {
int[] arr = {a, b, c};
Arrays.sort(arr);
int left_gap = arr[1] - arr[0];
int right_gap = arr[2] - arr[1];
int min_moves, max_moves;
if (left_gap == 1 && right_gap == 1) {
min_moves = 0;
} else if (left_gap <= 2 || right_gap <= 2) {
min_moves = 1;
} else {
min_moves = 2;
}
max_moves = (left_gap - 1) + (right_gap - 1);
return new int[]{min_moves, max_moves};
}
}
function numMovesStones(a, b, c) {
let arr = [a, b, c].sort((x, y) => x - y);
let left_gap = arr[1] - arr[0];
let right_gap = arr[2] - arr[1];
let min_moves, max_moves;
if (left_gap === 1 && right_gap === 1) {
min_moves = 0;
} else if (left_gap <= 2 || right_gap <= 2) {
min_moves = 1;
} else {
min_moves = 2;
}
max_moves = (left_gap - 1) + (right_gap - 1);
return [min_moves, max_moves];
}