Minimum Moves to Pick K Ones solution and explanation
The problem
You are given a binary array nums of length n, a positive integer k and a non-negative integer maxChanges.
Alice plays a game, where the goal is for Alice to pick up k ones from nums using the minimum number of moves. When the game starts, Alice picks up any index aliceIndex in the range [0, n - 1] and stands there. If nums[aliceIndex] == 1 , Alice picks up the one and nums[aliceIndex] becomes 0(this does not count as a move). After this, Alice can make any number of moves (including zero) where in each move Alice must perform exactly one of the following actions:
- Select any index
j != aliceIndexsuch thatnums[j] == 0and setnums[j] = 1. This action can be performed at mostmaxChangestimes. - Select any two adjacent indices
xandy(|x - y| == 1) such thatnums[x] == 1,nums[y] == 0, then swap their values (setnums[y] = 1andnums[x] = 0). Ify == aliceIndex, Alice picks up the one after this move andnums[y]becomes0.
Return the minimum number of moves required by Alice to pick exactly k ones.
Example 1:
Input: nums = [1,1,0,0,0,1,1,0,0,1], k = 3, maxChanges = 1
Output: 3
Explanation: Alice can pick up 3 ones in 3 moves, if Alice performs the following actions in each move when standing at aliceIndex == 1:
- At the start of the game Alice picks up the one and
nums[1]becomes0.numsbecomes[1,0,0,0,0,1,1,0,0,1]. - Select
j == 2and perform an action of the first type.numsbecomes[1,0,1,0,0,1,1,0,0,1] - Select
x == 2andy == 1, and perform an action of the second type.numsbecomes[1,1,0,0,0,1,1,0,0,1]. Asy == aliceIndex, Alice picks up the one andnumsbecomes[1,0,0,0,0,1,1,0,0,1]. - Select
x == 0andy == 1, and perform an action of the second type.numsbecomes[0,1,0,0,0,1,1,0,0,1]. Asy == aliceIndex, Alice picks up the one andnumsbecomes[0,0,0,0,0,1,1,0,0,1].
Note that it may be possible for Alice to pick up 3 ones using some other sequence of 3 moves.
Example 2:
Input: nums = [0,0,0,0], k = 2, maxChanges = 3
Output: 4
Explanation: Alice can pick up 2 ones in 4 moves, if Alice performs the following actions in each move when standing at aliceIndex == 0:
- Select
j == 1and perform an action of the first type.numsbecomes[0,1,0,0]. - Select
x == 1andy == 0, and perform an action of the second type.numsbecomes[1,0,0,0]. Asy == aliceIndex, Alice picks up the one andnumsbecomes[0,0,0,0]. - Select
j == 1again and perform an action of the first type.numsbecomes[0,1,0,0]. - Select
x == 1andy == 0again, and perform an action of the second type.numsbecomes[1,0,0,0]. Asy == aliceIndex, Alice picks up the one andnumsbecomes[0,0,0,0].
Constraints:
2 <= n <= 1050 <= nums[i] <= 11 <= k <= 1050 <= maxChanges <= 105maxChanges + sum(nums) >= k
Approach overview
Problem Overview: You are given a binary array and must determine the minimum number of moves required to pick exactly k ones. A move typically represents shifting positions so the chosen ones can be grouped efficiently. The challenge is minimizing total movement while selecting the best k ones from the array.
Approach 1: Sliding Window with Prefix Sums (O(n) time, O(n) space)
The optimal strategy focuses only on indices containing 1. First collect the positions of all ones. Then use a sliding window of size k over these positions to evaluate every possible group of k ones. The key insight: the minimum movement cost occurs when all ones move toward the median index in the window. To compute movement quickly, maintain a prefix sum array of the positions so the cost of moving the left and right halves toward the median can be calculated in constant time. As the window slides, update the cost using prefix sums instead of recomputing distances. This reduces the overall complexity to linear time.
Approach 2: Dynamic Programming (O(n * k) time, O(n * k) space)
A dynamic programming formulation considers the decision of selecting ones progressively from left to right. Define a DP state where dp[i][j] represents the minimum cost to pick j ones using the first i elements. When encountering a 1, either include it in the selected group or skip it. Transition costs account for how far the current one must move relative to previously chosen ones. Although this approach models the process clearly, it requires maintaining a large state table and recalculating movement costs frequently. Time complexity grows to O(n * k), making it slower for large inputs.
The sliding window technique works because movement cost is minimized around the median position. Using prefix sums allows constant‑time distance calculations for each candidate window. This combination of array traversal, window maintenance, and median-based distance minimization avoids expensive recomputation.
Recommended for interviews: The sliding window + prefix sum solution is the expected approach. Interviewers want to see that you reduce the problem to positions of ones, recognize the median property, and compute distances efficiently. A DP formulation shows reasoning about state transitions, but the optimal sliding window solution demonstrates stronger algorithmic insight and performance awareness.
Approach 1: Sliding Window Approach
We can use a sliding window approach to find the minimum number of moves to make k consecutive elements of the array equal to 1. This technique efficiently checks subarrays of length k.
def minMoves(nums, k, maxChanges):
left, right = 0, 0
zero_count, result = 0, len(nums) + 1
n = len(nums)
while right < n:
if nums[right] == 0:
zero_count += 1
right += 1
while zero_count > maxChanges:
if nums[left] == 0:
zero_count -= 1
left += 1
if right - left >= k:
result = min(result, zero_count)
return result
nums = [1,1,0,0,0,1,1,0,0,1]
k = 3
maxChanges = 1
print(minMoves(nums, k, maxChanges))import java.util.*;
public class Solution {
public static int minMoves(int[] nums, int k, int maxChanges) {
int left = 0, right = 0, zeroCount = 0, result = nums.length + 1;
int n = nums.length;
while (right < n) {
if (nums[right++] == 0) zeroCount++;
while (zeroCount > maxChanges) {
if (nums[left++] == 0) zeroCount--;
}
if (right - left >= k) {
result = Math.min(result, zeroCount);
}
}
return result;
}
public static void main(String[] args) {
int[] nums = {1,1,0,0,0,1,1,0,0,1};
int k = 3;
int maxChanges = 1;
System.out.println(minMoves(nums, k, maxChanges));
}
}#include <iostream>
#include <vector>
#include <climits>
using namespace std;
int minMoves(vector<int>& nums, int k, int maxChanges) {
int left = 0, right = 0, zeroCount = 0, result = INT_MAX, n = nums.size();
while (right < n) {
if (nums[right] == 0) zeroCount++;
right++;
while (zeroCount > maxChanges) {
if (nums[left] == 0) zeroCount--;
left++;
}
if (right - left >= k) {
result = min(result, zeroCount);
}
}
return result;
}
int main() {
vector<int> nums = {1,1,0,0,0,1,1,0,0,1};
int k = 3;
int maxChanges = 1;
cout << minMoves(nums, k, maxChanges) << endl;
return 0;
}function minMoves(nums, k, maxChanges) {
let left = 0, right = 0, zeroCount = 0, result = nums.length + 1;
while (right < nums.length) {
if (nums[right++] === 0) zeroCount++;
while (zeroCount > maxChanges) {
if (nums[left++] === 0) zeroCount--;
}
if (right - left >= k) {
result = Math.min(result, zeroCount);
}
}
return result;
}
let nums = [1,1,0,0,0,1,1,0,0,1];
let k = 3;
let maxChanges = 1;
console.log(minMoves(nums, k, maxChanges));#include <stdio.h>
int minMoves(int* nums, int n, int k, int maxChanges) {
int left = 0, right = 0, zeroCount = 0, result = n + 1;
while (right < n) {
if (nums[right] == 0) zeroCount++;
right++;
while (zeroCount > maxChanges) {
if (nums[left] == 0) zeroCount--;
left++;
}
if (right - left >= k) {
result = result > zeroCount ? zeroCount : result;
}
}
return result;
}
int main() {
int nums[] = {1,1,0,0,0,1,1,0,0,1};
int k = 3;
int maxChanges = 1;
int n = sizeof(nums) / sizeof(nums[0]);
printf("%d\n", minMoves(nums, n, k, maxChanges));
return 0;
}using System;
public class Solution {
public int MinMoves(int[] nums, int k, int maxChanges) {
int left = 0, right = 0, zeroCount = 0, result = nums.Length + 1;
int n = nums.Length;
while (right < n) {
if (nums[right++] == 0) zeroCount++;
while (zeroCount > maxChanges) {
if (nums[left++] == 0) zeroCount--;
}
if (right - left >= k) {
result = Math.Min(result, zeroCount);
}
}
return result;
}
public static void Main(String[] args) {
int[] nums = {1,1,0,0,0,1,1,0,0,1};
int k = 3;
int maxChanges = 1;
Solution sol = new Solution();
Console.WriteLine(sol.MinMoves(nums, k, maxChanges));
}
}The Python version follows the sliding window paradigm, iterating through the list and adjusting the window to keep zero flips minimal.
Time Complexity: O(n)
Space Complexity: O(1)
Approach 2: Dynamic Programming Approach
Here, dynamic programming techniques can be applied to solve the problem by saving state transformations and outcomes efficiently to determine minimum move counts required iteratively.
/* ... Placeholder for Python Dynamic Programming Solution ... *//* ... Placeholder for Java Dynamic Programming Solution ... *//* ... Placeholder for C++ Dynamic Programming Solution ... *//* ... Placeholder for JavaScript Dynamic Programming Solution ... *//* ... Placeholder for C Dynamic Programming Solution ... *//* ... Placeholder for C# Dynamic Programming Solution ... */Persisting move analyses across particular states expedites solution derivation significantly in the DP paradigm.
Time Complexity: O(n^2)
Space Complexity: O(n)
Approach 3: Greedy + Prefix Sum + Binary Search
We consider enumerating Alice's standing position i. For each i, we follow the strategy below:
- First, if the number at position
iis1, we can directly pick up a1without needing any moves. - Then, we pick up the number
1from both sides of positioni, which is action2, i.e., move the1from positioni-1to positioni, then pick it up; move the1from positioni+1to positioni, then pick it up. Each pick up of a1requires1move. - Next, we maximize the conversion of
0s at positionsi-1ori+1to1s using action1, then move them to positioniusing action2to pick them up. This continues until the number of1s picked up reacheskor the number of times action1is used reachesmaxChanges. Assuming the number of times action1is used isc, then a total of2cmoves are needed. - After utilizing action
1, if the number of1s picked up has not reachedk, we need to continue considering moving1s to positionifrom the intervals[1,..i-2]and[i+2,..n]using action2to pick them up. We can use binary search to determine the size of this interval so that the number of1s picked up reachesk. Specifically, we binary search for an interval sized, then within the intervals[i-d,..i-2]and[i+2,..i+d], we perform action2to move1s to positionifor pickup. If the number of1s picked up reachesk, we update the answer.
The time complexity is O(n times log n), and the space complexity is O(n). Here, n is the length of the array nums.
function minimumMoves(nums: number[], k: number, maxChanges: number): number {
const n = nums.length;
const cnt = Array(n + 1).fill(0);
const s = Array(n + 1).fill(0);
for (let i = 1; i <= n; i++) {
cnt[i] = cnt[i - 1] + nums[i - 1];
s[i] = s[i - 1] + i * nums[i - 1];
}
let ans = Infinity;
for (let i = 1; i <= n; i++) {
let t = 0;
let need = k - nums[i - 1];
for (let j of [i - 1, i + 1]) {
if (need > 0 && 1 <= j && j <= n && nums[j - 1] === 1) {
need--;
t++;
}
}
const c = Math.min(need, maxChanges);
need -= c;
t += c * 2;
if (need <= 0) {
ans = Math.min(ans, t);
continue;
}
let l = 2,
r = Math.max(i - 1, n - i);
while (l <= r) {
const mid = (l + r) >> 1;
const [l1, r1] = [Math.max(1, i - mid), Math.max(0, i - 2)];
const [l2, r2] = [Math.min(n + 1, i + 2), Math.min(n, i + mid)];
const c1 = cnt[r1] - cnt[l1 - 1];
const c2 = cnt[r2] - cnt[l2 - 1];
if (c1 + c2 >= need) {
const t1 = c1 * i - (s[r1] - s[l1 - 1]);
const t2 = s[r2] - s[l2 - 1] - c2 * i;
ans = Math.min(ans, t + t1 + t2);
r = mid - 1;
} else {
l = mid + 1;
}
}
}
return ans;
}func minimumMoves(nums []int, k int, maxChanges int) int64 {
n := len(nums)
cnt := make([]int, n+1)
s := make([]int, n+1)
for i := 1; i <= n; i++ {
cnt[i] = cnt[i-1] + nums[i-1]
s[i] = s[i-1] + i*nums[i-1]
}
ans := math.MaxInt64
for i := 1; i <= n; i++ {
t := 0
need := k - nums[i-1]
for _, j := range []int{i - 1, i + 1} {
if need > 0 && 1 <= j && j <= n && nums[j-1] == 1 {
need--
t++
}
}
c := min(need, maxChanges)
need -= c
t += c * 2
if need <= 0 {
ans = min(ans, t)
continue
}
l, r := 2, max(i-1, n-i)
for l <= r {
mid := (l + r) >> 1
l1, r1 := max(1, i-mid), max(0, i-2)
l2, r2 := min(n+1, i+2), min(n, i+mid)
c1 := cnt[r1] - cnt[l1-1]
c2 := cnt[r2] - cnt[l2-1]
if c1+c2 >= need {
t1 := c1*i - (s[r1] - s[l1-1])
t2 := s[r2] - s[l2-1] - c2*i
ans = min(ans, t+t1+t2)
r = mid - 1
} else {
l = mid + 1
}
}
}
return int64(ans)
}Complexity comparison
| Approach | Complexity |
|---|---|
| Sliding Window Approach | Time Complexity: O(n) |
| Dynamic Programming Approach | Time Complexity: O(n^2) |
| Greedy + Prefix Sum + Binary Search | – |
Complexity analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Sliding Window + Prefix Sum | O(n) | O(n) | Best general solution. Efficient for large arrays and commonly expected in interviews. |
| Dynamic Programming | O(n * k) | O(n * k) | Useful for understanding state transitions or when experimenting with different constraints. |
Frequently asked questions
Is Minimum Moves to Pick K Ones easy or hard?
Minimum Moves to Pick K Ones is classified as Hard on LeetCode with a relatively low acceptance rate. The difficulty comes from recognizing the median movement property and combining sliding window with prefix sums to avoid quadratic calculations.
Minimum Moves to Pick K Ones Python/Java solution
Most implementations follow the same pattern: collect indices of ones, build a prefix sum array, and slide a window of size k to compute minimal movement cost around the median. The logic translates directly across Python, Java, C++, and other languages with O(n) complexity.
How to solve Minimum Moves to Pick K Ones in O(n)?
First record the indices of all elements equal to 1. Use a sliding window of size k across these indices and treat the middle element as the median position. Precompute prefix sums of indices so the cost of moving the left and right halves to the median can be calculated quickly, allowing the window to slide in linear time.
What is the best approach for Minimum Moves to Pick K Ones?
The most efficient solution uses a sliding window over the indices of ones combined with prefix sums. By centering movements around the median element of each window, the total distance can be computed in O(1) per window. This produces an overall O(n) time complexity and O(n) space complexity.
Is Minimum Moves to Pick K Ones asked at Google/Amazon/Meta?
Problems involving grouping elements with minimum moves, sliding windows, and prefix sums frequently appear in interviews at companies like Google, Amazon, and Meta. Variants of this problem test understanding of median-based distance minimization and efficient window processing.
What data structure is used in Minimum Moves to Pick K Ones?
The main structures are arrays for storing positions of ones and prefix sum arrays for fast range calculations. The algorithm also relies on the sliding window technique and median-based distance computation.
What is the time complexity of Minimum Moves to Pick K Ones?
The optimal sliding window solution runs in O(n) time where n is the length of the array. Each index is processed once while prefix sums allow constant‑time movement cost calculations. Space complexity is O(n) for storing positions and prefix sums.



