There are M people sitting in a row of N seats, where M < N. Your task is to redistribute people such that there are no gaps between any of them, while keeping overall movement to a minimum.
For example, suppose you are faced with an input of [0, 1, 1, 0, 1, 0, 0, 0, 1], where 0 represents an empty seat and 1 represents a person. In this case, one solution would be to place the person on the right in the fourth seat. We can consider the cost of a solution to be the sum of the absolute distance each person must move, so that the cost here would be five.
Given an input such as the one above, return the lowest possible cost of moving people to remove all gaps.
Input: [0,1,1,0,1,0,0,0,1]Output: 5Explanation:
People are at positions [1,2,4,8]. To remove gaps, we can move them to [1,2,3,4].Cost =|1-1|+|2-2|+|4-3|+|8-4|=0+0+1+4=5.
Input: [1,0,0,1,1,0,1]Output: 1Explanation:
People are at positions [0,3,4,6]. To remove gaps, we can move them to [2,3,4,5].Cost =|0-2|+|3-3|+|4-4|+|6-5|=2+0+0+1=3.Alternative: move to [0,1,2,3]with cost =|0-0|+|3-1|+|4-2|+|6-3|=0+2+2+3=7.Or move to [3,4,5,6]with cost =|0-3|+|3-3|+|4-4|+|6-6|=3+0+0+0=3.Best is moving to positions [3,4,5,6] or [0,1,2,3] but actually optimal is[1,2,3,4]with cost 1.
Input: [1,0,1]Output: 0Explanation:
People are at positions [0,2]. To remove gaps, move them to [0,1] or [1,2].Cost for[0,1]=|0-0|+|2-1|=0+1=1.Cost for[1,2]=|0-1|+|2-2|=1+0=1.Actually both have cost 1, but optimal arrangement is[0,1] or [1,2]with cost 1.Wait, let me recalculate: minimum cost is1.
To minimize the total movement cost, we need to find the optimal target window of consecutive seats where all people should be placed. The key insight is that for any fixed window of M consecutive seats, the optimal assignment minimizes the sum of absolute distances, which is achieved by matching people to seats in sorted order (closest person to leftmost seat, etc.).
classSolution {
public:int minCostToRemoveGaps(vector<int>& seats) {
vector<int> people;
int n = seats.size();
// Find positions of all people
for (int i =0; i < n; i++) {
if (seats[i] ==1) {
people.push_back(i);
}
}
int m = people.size();
if (m <=1) return0;
int minCost = INT_MAX;
// Try all possible starting positions for consecutive block
for (int start =0; start <= n - m; start++) {
int cost =0;
for (int i =0; i < m; i++) {
cost += abs(people[i] - (start + i));
}
minCost = min(minCost, cost);
}
return minCost;
}
};
classSolution {
publicintminCostToRemoveGaps(int[] seats) {
List<Integer> people =new ArrayList<>();
int n = seats.length;
// Find positions of all peoplefor (int i = 0; i < n; i++) {
if (seats[i]== 1) {
people.add(i);
}
}
int m = people.size();
if (m <= 1) return 0;
int minCost = Integer.MAX_VALUE;
// Try all possible starting positions for consecutive blockfor (int start = 0; start <= n - m; start++) {
int cost = 0;
for (int i = 0; i < m; i++) {
cost += Math.abs(people.get(i) - (start + i));
}
minCost = Math.min(minCost, cost);
}
return minCost;
}
}
classSolution:
defminCostToRemoveGaps(self, seats: List[int]) -> int:
people = []
n = len(seats)
# Find positions of all peoplefor i in range(n):
if seats[i] ==1:
people.append(i)
m = len(people)
if m <=1:
return0 min_cost = float('inf')
# Try all possible starting positions for consecutive blockfor start in range(n - m +1):
cost =0for i in range(m):
cost += abs(people[i] - (start + i))
min_cost = min(min_cost, cost)
return min_cost
⏰ Time complexity: O(N × M), where N is the number of seats and M is the number of people. We try N-M+1 starting positions and for each calculate cost in O(M) time
🧺 Space complexity: O(M), for storing the positions of people
We can optimize the sliding window approach by using prefix sums. Instead of recalculating the entire cost for each window, we can use the relationship between consecutive windows to update the cost incrementally. When we move the target window one position to the right, some people move closer and others move farther.
classSolution {
public:int minCostToRemoveGapsOptimized(vector<int>& seats) {
vector<int> people;
int n = seats.size();
for (int i =0; i < n; i++) {
if (seats[i] ==1) {
people.push_back(i);
}
}
int m = people.size();
if (m <=1) return0;
// Calculate initial cost for window [0, m-1]
int cost =0;
for (int i =0; i < m; i++) {
cost += abs(people[i] - i);
}
int minCost = cost;
// Slide window and update cost incrementally
for (int start =1; start <= n - m; start++) {
// When moving window from [start-1, start+m-2] to [start, start+m-1]
for (int i =0; i < m; i++) {
// Remove old cost and add new cost
cost -= abs(people[i] - (start -1+ i));
cost += abs(people[i] - (start + i));
}
minCost = min(minCost, cost);
}
return minCost;
}
};
classSolution {
publicintminCostToRemoveGapsOptimized(int[] seats) {
List<Integer> people =new ArrayList<>();
int n = seats.length;
for (int i = 0; i < n; i++) {
if (seats[i]== 1) {
people.add(i);
}
}
int m = people.size();
if (m <= 1) return 0;
// Calculate initial cost for window [0, m-1]int cost = 0;
for (int i = 0; i < m; i++) {
cost += Math.abs(people.get(i) - i);
}
int minCost = cost;
// Slide window and update cost incrementallyfor (int start = 1; start <= n - m; start++) {
int newCost = 0;
for (int i = 0; i < m; i++) {
newCost += Math.abs(people.get(i) - (start + i));
}
minCost = Math.min(minCost, newCost);
}
return minCost;
}
}
classSolution:
defminCostToRemoveGapsOptimized(self, seats: List[int]) -> int:
people = []
n = len(seats)
for i in range(n):
if seats[i] ==1:
people.append(i)
m = len(people)
if m <=1:
return0# Calculate initial cost for window [0, m-1] cost = sum(abs(people[i] - i) for i in range(m))
min_cost = cost
# Slide window and update cost incrementallyfor start in range(1, n - m +1):
new_cost = sum(abs(people[i] - (start + i)) for i in range(m))
min_cost = min(min_cost, new_cost)
return min_cost