class Solution:
def minMoves(self, nums: List[int], k: int) -> int:
ones = [i for i, num in enumerate(nums) if num == 1]
pre_sum = [0]
for pos in ones:
pre_sum.append(pre_sum[-1] + pos)
min_swaps = float('inf')
for i in range(len(ones) - k + 1):
mid = i + k // 2
median = ones[mid]
if k % 2 == 1:
left = pre_sum[mid] - pre_sum[i]
right = pre_sum[i + k] - pre_sum[mid + 1]
swaps = (median * (mid - i) - left) + (right - median * (i + k - mid - 1))
else:
left = pre_sum[mid] - pre_sum[i]
right = pre_sum[i + k] - pre_sum[mid]
swaps = (median * (mid - i) - left) + (right - median * (i + k - mid))
# Subtract the "ideal" distances (0,1,2...) to account for adjacency
offset = (k // 2) * ((k + 1) // 2)
swaps -= offset
min_swaps = min(min_swaps, swaps)
return min_swaps
class Solution {
public:
int minMoves(vector<int>& nums, int k) {
vector<int> ones;
for (int i = 0; i < nums.size(); ++i) {
if (nums[i] == 1) ones.push_back(i);
}
vector<long long> pre_sum(ones.size() + 1, 0);
for (int i = 0; i < ones.size(); ++i) {
pre_sum[i+1] = pre_sum[i] + ones[i];
}
int res = INT_MAX;
for (int i = 0; i + k <= ones.size(); ++i) {
int mid = i + k / 2;
int median = ones[mid];
long long left, right, swaps;
if (k % 2 == 1) {
left = pre_sum[mid] - pre_sum[i];
right = pre_sum[i+k] - pre_sum[mid+1];
swaps = (long long)median * (mid - i) - left + right - (long long)median * (i + k - mid - 1);
} else {
left = pre_sum[mid] - pre_sum[i];
right = pre_sum[i+k] - pre_sum[mid];
swaps = (long long)median * (mid - i) - left + right - (long long)median * (i + k - mid);
}
int offset = (k / 2) * ((k + 1) / 2);
swaps -= offset;
res = min(res, (int)swaps);
}
return res;
}
};
class Solution {
public int minMoves(int[] nums, int k) {
List<Integer> ones = new ArrayList<>();
for (int i = 0; i < nums.length; i++) {
if (nums[i] == 1) ones.add(i);
}
int n = ones.size();
long[] preSum = new long[n + 1];
for (int i = 0; i < n; i++) {
preSum[i + 1] = preSum[i] + ones.get(i);
}
int minSwaps = Integer.MAX_VALUE;
for (int i = 0; i + k <= n; i++) {
int mid = i + k / 2;
int median = ones.get(mid);
long left, right, swaps;
if (k % 2 == 1) {
left = preSum[mid] - preSum[i];
right = preSum[i + k] - preSum[mid + 1];
swaps = median * (mid - i) - left + right - median * (i + k - mid - 1);
} else {
left = preSum[mid] - preSum[i];
right = preSum[i + k] - preSum[mid];
swaps = median * (mid - i) - left + right - median * (i + k - mid);
}
int offset = (k / 2) * ((k + 1) / 2);
swaps -= offset;
minSwaps = (int)Math.min(minSwaps, swaps);
}
return minSwaps;
}
}
var minMoves = function(nums, k) {
let ones = [];
for (let i = 0; i < nums.length; ++i) {
if (nums[i] === 1) ones.push(i);
}
let preSum = [0];
for (let pos of ones) {
preSum.push(preSum[preSum.length - 1] + pos);
}
let minSwaps = Infinity;
for (let i = 0; i + k <= ones.length; ++i) {
let mid = i + Math.floor(k / 2);
let median = ones[mid];
let left, right, swaps;
if (k % 2 === 1) {
left = preSum[mid] - preSum[i];
right = preSum[i + k] - preSum[mid + 1];
swaps = median * (mid - i) - left + right - median * (i + k - mid - 1);
} else {
left = preSum[mid] - preSum[i];
right = preSum[i + k] - preSum[mid];
swaps = median * (mid - i) - left + right - median * (i + k - mid);
}
let offset = Math.floor(k / 2) * Math.ceil(k / 2);
swaps -= offset;
minSwaps = Math.min(minSwaps, swaps);
}
return minSwaps;
};
nums
(containing only 0s and 1s), and an integer k
, you are to find the minimum number of adjacent swaps required to group exactly k
ones together in consecutive positions in the array. Swapping is allowed only between adjacent elements, and you can swap as many times as needed. The output should be the minimum number of swaps needed to achieve this grouping.
k
ones together (no more, no less).k
ones in nums
.k
ones together, but this quickly becomes infeasible for large arrays. The key is to realize that the only elements that matter are the positions of the 1s themselves—since 0s can only be swapped past, not used in the group.
Imagine lining up the 1s and trying to move them into a block. The minimum number of swaps is achieved when the 1s are as close together as possible, ideally centered around a median position. This is because moving all numbers toward the median minimizes the total distance. The challenge is to efficiently compute the total number of swaps needed for every possible group of k
ones.
To optimize, we:
nums
.k
consecutive 1s, calculate the number of swaps needed to bring them together.nums
and record the positions of all 1s in a separate list.k
in the 1s' positions, find the "median" position. This is the target location to which all 1s in the window will be moved, as this minimizes the total distance (and thus swaps).nums = [1,0,0,1,0,1]
, k = 2
nums
.k
ones. By using prefix sums and sliding windows, we can efficiently calculate the minimum number of adjacent swaps needed. This method is elegant because it reduces a seemingly complex problem to simple arithmetic over preprocessed arrays, making it both fast and easy to understand.