3086. Minimum Moves to Pick K Ones
Problem Description
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 she needs to collect exactly k
ones from the array using the minimum number of moves.
Game Rules:
- Alice starts by choosing any index
aliceIndex
in the range[0, n-1]
to stand at - If
nums[aliceIndex] == 1
, Alice immediately picks up that one (settingnums[aliceIndex] = 0
) without using any moves
Available Actions (each counts as one move):
- Action 1: Select any index
j ≠ aliceIndex
wherenums[j] == 0
and change it to1
. This action can be performed at mostmaxChanges
times. - Action 2: Select two adjacent indices
x
andy
(where|x - y| == 1
) such thatnums[x] == 1
andnums[y] == 0
, then swap their values. If after swappingy == aliceIndex
, Alice automatically picks up the one at positiony
(setting it back to0
).
The goal is to find the minimum number of moves Alice needs to collect exactly k
ones.
Example Strategy:
- Alice can use Action 1 to create ones at convenient locations (limited by
maxChanges
) - Alice can use Action 2 to slide existing ones toward her position through adjacent swaps
- The challenge is finding the optimal starting position and combination of actions to minimize total moves
The problem requires determining the best starting position for Alice and the optimal sequence of actions to collect k
ones with the fewest moves possible.
Intuition
The key insight is that we should try every possible starting position for Alice and find the one that minimizes the total moves.
For any starting position i
, we can think about the most efficient order to collect ones:
-
Free pickup: If there's already a one at position
i
, we get it for free (0 moves). -
Adjacent ones: The next cheapest ones to collect are those immediately adjacent to Alice (at positions
i-1
andi+1
). Each of these only costs 1 move since we can directly swap them to Alice's position. -
Creating ones nearby: After grabbing adjacent ones, we should consider using Action 1 (creating new ones from zeros). The optimal strategy is to create these ones at positions
i-1
ori+1
(if they're currently 0), then immediately swap them to positioni
. This costs 2 moves per one collected (1 move to create, 1 move to swap). -
Distant ones: Only after exhausting our
maxChanges
should we consider moving ones from farther away. Moving a one from distanced
costsd
moves (we needd
swaps to bring it to Alice).
The crucial realization is that for distant ones, we want to minimize the total distance traveled. This means we should collect the closest ones first. We can use binary search to find the minimum radius around position i
that contains enough ones to reach our target k
.
To efficiently calculate the cost of moving distant ones, we use prefix sums:
cnt[i]
: count of ones up to positioni
s[i]
: sum of positions of all ones up to positioni
The cost to move all ones in range [l, r]
to position i
is:
- For ones to the left of
i
:count * i - sum_of_positions
- For ones to the right of
i
:sum_of_positions - count * i
By trying all starting positions and applying this greedy strategy at each position, we can find the global minimum number of moves needed.
Learn more about Greedy, Prefix Sum and Sliding Window patterns.
Solution Approach
The solution implements the greedy strategy with prefix sums and binary search for efficiency.
Step 1: Build Prefix Arrays
cnt = [0] * (n + 1) # cnt[i] = count of ones in nums[0:i] s = [0] * (n + 1) # s[i] = sum of positions of ones in nums[0:i]
We use 1-based indexing for easier calculation. For each position i
, we track:
cnt[i]
: total number of ones up to positioni
s[i]
: sum of all positions where ones appear up to positioni
Step 2: Enumerate Each Starting Position
For each possible starting position i
(1 to n):
-
Pick up the free one if
nums[i-1] == 1
:- Set
need = k - x
wherex
is 1 if there's a one at positioni
, else 0 - Cost: 0 moves
- Set
-
Collect adjacent ones (positions
i-1
andi+1
):for j in (i - 1, i + 1): if need > 0 and 1 <= j <= n and nums[j - 1] == 1: need -= 1 t += 1 # Each adjacent one costs 1 move
-
Use Action 1 to create ones:
c = min(need, maxChanges) need -= c t += c * 2 # Each created one costs 2 moves (create + swap)
We create at most
min(need, maxChanges)
ones and place them optimally at adjacent positions. -
If still need more ones, use binary search to find the minimum radius:
l, r = 2, max(i - 1, n - i) while l <= r: mid = (l + r) >> 1
- Search for the smallest distance
mid
such that intervals[i-mid, i-2]
and[i+2, i+mid]
contain at leastneed
remaining ones - Calculate ranges excluding adjacent positions (already processed):
- Left range:
[max(1, i-mid), max(0, i-2)]
- Right range:
[min(n+1, i+2), min(n, i+mid)]
- Left range:
- Search for the smallest distance
-
Calculate the cost using prefix sums:
c1 = cnt[r1] - cnt[l1 - 1] # Count of ones on the left c2 = cnt[r2] - cnt[l2 - 1] # Count of ones on the right if c1 + c2 >= need: t1 = c1 * i - (s[r1] - s[l1 - 1]) # Cost for left ones t2 = s[r2] - s[l2 - 1] - c2 * i # Cost for right ones
- For ones to the left of
i
: each one at positionj
costsi - j
moves - For ones to the right of
i
: each one at positionj
costsj - i
moves - Total cost =
sum of distances
=count * i - sum_of_positions
(left) +sum_of_positions - count * i
(right)
- For ones to the left of
Step 3: Track Minimum After calculating the cost for each starting position, we keep track of the minimum:
ans = min(ans, t + t1 + t2)
The algorithm returns the minimum number of moves across all possible starting positions.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a concrete example to illustrate the solution approach.
Example: nums = [1, 0, 0, 1, 0, 1]
, k = 2
, maxChanges = 1
We need to collect exactly 2 ones using the minimum number of moves.
Step 1: Build Prefix Arrays
- Original array (1-indexed):
[1, 0, 0, 1, 0, 1]
- Ones are at positions: 1, 4, 6
cnt = [0, 1, 1, 1, 2, 2, 3]
(cumulative count of ones)s = [0, 1, 1, 1, 5, 5, 11]
(cumulative sum of positions with ones)
Step 2: Try Each Starting Position
Let's examine starting position i = 4
(index 3 in 0-based):
-
Free pickup:
nums[3] = 1
, so Alice gets 1 one for freeneed = k - 1 = 2 - 1 = 1
- Cost so far: 0 moves
-
Check adjacent positions (i-1=3 and i+1=5):
- Position 3:
nums[2] = 0
(no one here) - Position 5:
nums[4] = 0
(no one here) - Still need: 1 one
- Cost so far: 0 moves
- Position 3:
-
Use Action 1 (create ones):
- Can create
min(need, maxChanges) = min(1, 1) = 1
one - Create a one at position 3 or 5, then swap to position 4
need = 1 - 1 = 0
- Cost: 0 + 1×2 = 2 moves total
- Can create
-
Binary search for distant ones: Not needed since
need = 0
Total cost for starting at position 4: 2 moves
Let's also try starting position i = 1
:
-
Free pickup:
nums[0] = 1
, get 1 one for freeneed = 2 - 1 = 1
- Cost: 0 moves
-
Check adjacent positions (only i+1=2 since i-1=0 is out of bounds):
- Position 2:
nums[1] = 0
(no one here) - Still need: 1 one
- Cost: 0 moves
- Position 2:
-
Use Action 1:
- Create
min(1, 1) = 1
one at position 2 - Swap to position 1
need = 1 - 1 = 0
- Cost: 0 + 1×2 = 2 moves
- Create
Total cost for starting at position 1: 2 moves
Let's try starting position i = 2
(where there's no initial one):
-
Free pickup:
nums[1] = 0
, no free oneneed = 2
- Cost: 0 moves
-
Check adjacent positions (i-1=1 and i+1=3):
- Position 1:
nums[0] = 1
- can swap this one! need = 2 - 1 = 1
- Cost: 0 + 1 = 1 move
- Position 3:
nums[2] = 0
(no one here)
- Position 1:
-
Use Action 1:
- Create
min(1, 1) = 1
one need = 1 - 1 = 0
- Cost: 1 + 1×2 = 3 moves
- Create
Total cost for starting at position 2: 3 moves
Step 3: Find Minimum After checking all positions, the minimum is 2 moves (achieved at positions 1 and 4).
The algorithm correctly identifies that starting at a position with an existing one and using our single maxChanges
to create and collect another one nearby is optimal for this example.
Solution Implementation
1class Solution:
2 def minimumMoves(self, nums: List[int], k: int, maxChanges: int) -> int:
3 n = len(nums)
4
5 # Prefix arrays for count and weighted sum
6 # cnt[i] = count of 1s in nums[0:i]
7 # weighted_sum[i] = sum of (index+1) * value for nums[0:i]
8 cnt = [0] * (n + 1)
9 weighted_sum = [0] * (n + 1)
10
11 for i, val in enumerate(nums, 1):
12 cnt[i] = cnt[i - 1] + val
13 weighted_sum[i] = weighted_sum[i - 1] + i * val
14
15 min_moves = float('inf')
16
17 # Try each position as the collection point
18 for i, val in enumerate(nums, 1):
19 moves = 0
20 remaining_needed = k - val # How many more 1s we need after taking current position
21
22 # First, try to collect from immediate neighbors (cost = 1 move each)
23 for neighbor_pos in (i - 1, i + 1):
24 if remaining_needed > 0 and 1 <= neighbor_pos <= n and nums[neighbor_pos - 1] == 1:
25 remaining_needed -= 1
26 moves += 1
27
28 # Use maxChanges to create 1s and immediately collect them (cost = 2 moves each)
29 changes_to_use = min(remaining_needed, maxChanges)
30 remaining_needed -= changes_to_use
31 moves += changes_to_use * 2
32
33 # If we've collected enough, update answer
34 if remaining_needed <= 0:
35 min_moves = min(min_moves, moves)
36 continue
37
38 # Binary search for the minimum radius to collect remaining_needed 1s
39 left, right = 2, max(i - 1, n - i)
40
41 while left <= right:
42 mid_radius = (left + right) >> 1
43
44 # Define ranges for collecting (excluding immediate neighbors already considered)
45 left_range_start = max(1, i - mid_radius)
46 left_range_end = max(0, i - 2)
47 right_range_start = min(n + 1, i + 2)
48 right_range_end = min(n, i + mid_radius)
49
50 # Count 1s in left and right ranges
51 left_count = cnt[left_range_end] - cnt[left_range_start - 1]
52 right_count = cnt[right_range_end] - cnt[right_range_start - 1]
53
54 if left_count + right_count >= remaining_needed:
55 # Calculate cost to move 1s from left range to position i
56 left_cost = left_count * i - (weighted_sum[left_range_end] - weighted_sum[left_range_start - 1])
57 # Calculate cost to move 1s from right range to position i
58 right_cost = weighted_sum[right_range_end] - weighted_sum[right_range_start - 1] - right_count * i
59
60 min_moves = min(min_moves, moves + left_cost + right_cost)
61 right = mid_radius - 1 # Try smaller radius
62 else:
63 left = mid_radius + 1 # Need larger radius
64
65 return min_moves
66
1class Solution {
2 public long minimumMoves(int[] nums, int k, int maxChanges) {
3 int n = nums.length;
4
5 // Prefix sum arrays for optimization
6 // prefixCount[i] = count of 1s in nums[0...i-1]
7 // prefixWeightedSum[i] = sum of (index * value) for nums[0...i-1]
8 int[] prefixCount = new int[n + 1];
9 long[] prefixWeightedSum = new long[n + 1];
10
11 // Build prefix sum arrays
12 for (int i = 1; i <= n; ++i) {
13 prefixCount[i] = prefixCount[i - 1] + nums[i - 1];
14 prefixWeightedSum[i] = prefixWeightedSum[i - 1] + i * nums[i - 1];
15 }
16
17 long minMoves = Long.MAX_VALUE;
18
19 // Try each position as the collection point
20 for (int position = 1; position <= n; ++position) {
21 long currentMoves = 0;
22 int remaining = k - nums[position - 1]; // Items still needed after taking current position
23
24 // First, try to collect from immediate neighbors (distance = 1)
25 for (int neighborIdx = position - 1; neighborIdx <= position + 1; neighborIdx += 2) {
26 if (remaining > 0 && 1 <= neighborIdx && neighborIdx <= n && nums[neighborIdx - 1] == 1) {
27 remaining--;
28 currentMoves++;
29 }
30 }
31
32 // Use maxChanges to create and collect items (cost = 2 per item)
33 int changesUsed = Math.min(remaining, maxChanges);
34 remaining -= changesUsed;
35 currentMoves += changesUsed * 2;
36
37 // If we've collected enough items, update answer and continue
38 if (remaining <= 0) {
39 minMoves = Math.min(minMoves, currentMoves);
40 continue;
41 }
42
43 // Binary search for the minimum radius to collect remaining items
44 int left = 2, right = Math.max(position - 1, n - position);
45
46 while (left <= right) {
47 int radius = (left + right) >> 1;
48
49 // Define search ranges (excluding immediate neighbors already processed)
50 int leftRangeStart = Math.max(1, position - radius);
51 int leftRangeEnd = Math.max(0, position - 2);
52 int rightRangeStart = Math.min(n + 1, position + 2);
53 int rightRangeEnd = Math.min(n, position + radius);
54
55 // Count available items in both ranges
56 int leftCount = prefixCount[leftRangeEnd] - prefixCount[leftRangeStart - 1];
57 int rightCount = prefixCount[rightRangeEnd] - prefixCount[rightRangeStart - 1];
58
59 if (leftCount + rightCount >= remaining) {
60 // Calculate total distance to collect items from both sides
61 long leftDistance = 1L * leftCount * position - (prefixWeightedSum[leftRangeEnd] - prefixWeightedSum[leftRangeStart - 1]);
62 long rightDistance = prefixWeightedSum[rightRangeEnd] - prefixWeightedSum[rightRangeStart - 1] - 1L * rightCount * position;
63
64 minMoves = Math.min(minMoves, currentMoves + leftDistance + rightDistance);
65 right = radius - 1; // Try smaller radius
66 } else {
67 left = radius + 1; // Need larger radius
68 }
69 }
70 }
71
72 return minMoves;
73 }
74}
75
1class Solution {
2public:
3 long long minimumMoves(vector<int>& nums, int k, int maxChanges) {
4 int n = nums.size();
5
6 // Prefix sum arrays
7 // prefixCount[i] = count of 1s in nums[0..i-1]
8 // prefixWeightedSum[i] = sum of (index+1) * nums[index] for nums[0..i-1]
9 vector<int> prefixCount(n + 1, 0);
10 vector<long long> prefixWeightedSum(n + 1, 0);
11
12 // Build prefix sums
13 for (int i = 1; i <= n; ++i) {
14 prefixCount[i] = prefixCount[i - 1] + nums[i - 1];
15 prefixWeightedSum[i] = prefixWeightedSum[i - 1] + 1LL * i * nums[i - 1];
16 }
17
18 long long minMoves = LLONG_MAX;
19
20 // Try each position as the collection point
21 for (int position = 1; position <= n; ++position) {
22 long long currentMoves = 0;
23 int remaining = k - nums[position - 1]; // Ones still needed after taking current position
24
25 // First, collect adjacent ones (distance 1) without changes
26 for (int adjacentPos = position - 1; adjacentPos <= position + 1; adjacentPos += 2) {
27 if (remaining > 0 && 1 <= adjacentPos && adjacentPos <= n && nums[adjacentPos - 1] == 1) {
28 --remaining;
29 ++currentMoves; // Cost 1 to collect adjacent one
30 }
31 }
32
33 // Use maxChanges to create and collect ones (cost 2 per one)
34 int changesUsed = min(remaining, maxChanges);
35 remaining -= changesUsed;
36 currentMoves += changesUsed * 2;
37
38 // If we've collected enough ones, update answer
39 if (remaining <= 0) {
40 minMoves = min(minMoves, currentMoves);
41 continue;
42 }
43
44 // Binary search for minimum radius to collect remaining ones
45 int left = 2, right = max(position - 1, n - position);
46
47 while (left <= right) {
48 int radius = (left + right) / 2;
49
50 // Define search ranges (excluding adjacent positions already checked)
51 int leftRangeStart = max(1, position - radius);
52 int leftRangeEnd = max(0, position - 2);
53 int rightRangeStart = min(n + 1, position + 2);
54 int rightRangeEnd = min(n, position + radius);
55
56 // Count ones in left and right ranges
57 int leftCount = prefixCount[leftRangeEnd] - prefixCount[leftRangeStart - 1];
58 int rightCount = prefixCount[rightRangeEnd] - prefixCount[rightRangeStart - 1];
59
60 if (leftCount + rightCount >= remaining) {
61 // Calculate total distance to move ones from left range
62 long long leftCost = 1LL * leftCount * position -
63 (prefixWeightedSum[leftRangeEnd] - prefixWeightedSum[leftRangeStart - 1]);
64
65 // Calculate total distance to move ones from right range
66 long long rightCost = (prefixWeightedSum[rightRangeEnd] - prefixWeightedSum[rightRangeStart - 1]) -
67 1LL * rightCount * position;
68
69 minMoves = min(minMoves, currentMoves + leftCost + rightCost);
70 right = radius - 1; // Try smaller radius
71 } else {
72 left = radius + 1; // Need larger radius
73 }
74 }
75 }
76
77 return minMoves;
78 }
79};
80
1/**
2 * Finds the minimum number of moves to collect k ones in the array
3 * @param nums - Binary array containing 0s and 1s
4 * @param k - Number of ones to collect
5 * @param maxChanges - Maximum number of changes allowed (0 to 1 conversions)
6 * @returns Minimum number of moves required
7 */
8function minimumMoves(nums: number[], k: number, maxChanges: number): number {
9 const arrayLength = nums.length;
10
11 // Prefix sum arrays for counting ones and calculating weighted sums
12 const onesCount = Array(arrayLength + 1).fill(0);
13 const weightedSum = Array(arrayLength + 1).fill(0);
14
15 // Build prefix sum arrays
16 // onesCount[i] = number of ones in nums[0...i-1]
17 // weightedSum[i] = sum of (index+1) * value for nums[0...i-1]
18 for (let i = 1; i <= arrayLength; i++) {
19 onesCount[i] = onesCount[i - 1] + nums[i - 1];
20 weightedSum[i] = weightedSum[i - 1] + i * nums[i - 1];
21 }
22
23 let minMoves = Infinity;
24
25 // Try each position as the collection point
26 for (let position = 1; position <= arrayLength; position++) {
27 let totalMoves = 0;
28 let remainingOnes = k - nums[position - 1]; // Ones still needed after taking current position
29
30 // First, try to collect ones from immediate neighbors (distance 1)
31 for (let neighborIndex of [position - 1, position + 1]) {
32 if (remainingOnes > 0 &&
33 neighborIndex >= 1 &&
34 neighborIndex <= arrayLength &&
35 nums[neighborIndex - 1] === 1) {
36 remainingOnes--;
37 totalMoves++; // Cost 1 move for adjacent position
38 }
39 }
40
41 // Use changes to create ones at distance 2 (most efficient for changes)
42 const changesUsed = Math.min(remainingOnes, maxChanges);
43 remainingOnes -= changesUsed;
44 totalMoves += changesUsed * 2; // Each change costs 2 moves
45
46 // If we've collected enough ones, update answer
47 if (remainingOnes <= 0) {
48 minMoves = Math.min(minMoves, totalMoves);
49 continue;
50 }
51
52 // Binary search for minimum radius to collect remaining ones
53 let searchLeft = 2;
54 let searchRight = Math.max(position - 1, arrayLength - position);
55
56 while (searchLeft <= searchRight) {
57 const radius = (searchLeft + searchRight) >> 1;
58
59 // Define left range [l1, r1] and right range [l2, r2]
60 // Exclude positions within distance 1 (already handled)
61 const leftRangeStart = Math.max(1, position - radius);
62 const leftRangeEnd = Math.max(0, position - 2);
63 const rightRangeStart = Math.min(arrayLength + 1, position + 2);
64 const rightRangeEnd = Math.min(arrayLength, position + radius);
65
66 // Count ones in left and right ranges using prefix sums
67 const leftOnes = onesCount[leftRangeEnd] - onesCount[leftRangeStart - 1];
68 const rightOnes = onesCount[rightRangeEnd] - onesCount[rightRangeStart - 1];
69
70 if (leftOnes + rightOnes >= remainingOnes) {
71 // Calculate move cost for left range (positions < current)
72 const leftMoveCost = leftOnes * position - (weightedSum[leftRangeEnd] - weightedSum[leftRangeStart - 1]);
73 // Calculate move cost for right range (positions > current)
74 const rightMoveCost = (weightedSum[rightRangeEnd] - weightedSum[rightRangeStart - 1]) - rightOnes * position;
75
76 minMoves = Math.min(minMoves, totalMoves + leftMoveCost + rightMoveCost);
77 searchRight = radius - 1; // Try smaller radius
78 } else {
79 searchLeft = radius + 1; // Need larger radius
80 }
81 }
82 }
83
84 return minMoves;
85}
86
Time and Space Complexity
Time Complexity: O(n × log n)
The algorithm iterates through each position i
in the array (outer loop runs n
times). For each position, it performs a binary search to find the optimal range for collecting ones. The binary search runs in O(log n)
time since it searches within a range from 2 to max(i - 1, n - i)
, which is at most n
. All operations inside the binary search (calculating prefix sums, counting ones) are done in constant time due to preprocessing. Therefore, the overall time complexity is O(n × log n)
.
Space Complexity: O(n)
The algorithm uses two auxiliary arrays: cnt
(prefix sum array for counting ones) and s
(weighted prefix sum array), each of size n + 1
. These arrays require O(n)
space. The remaining variables (ans
, t
, need
, l
, r
, etc.) use constant space. Thus, the total space complexity is O(n)
.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Incorrect Handling of Partial Collection from Ranges
The Pitfall:
The current implementation calculates the cost assuming we take ALL ones from both the left and right ranges when left_count + right_count >= remaining_needed
. However, we only need remaining_needed
ones, not all available ones. This leads to an overestimation of the minimum cost.
Why It Happens: When binary searching for the minimum radius, once we find a radius where enough ones are available, we calculate:
left_cost = left_count * i - (weighted_sum[left_range_end] - weighted_sum[left_range_start - 1]) right_cost = weighted_sum[right_range_end] - weighted_sum[right_range_start - 1] - right_count * i
This computes the cost to move ALL left_count + right_count
ones, but we might only need a subset.
Example Scenario:
- Position i = 5, remaining_needed = 3
- Left range has 2 ones at positions [2, 3]
- Right range has 4 ones at positions [7, 8, 9, 10]
- Current code calculates cost for all 6 ones, but we only need 3
Solution:
We need to select the closest remaining_needed
ones from the combined ranges. The optimal strategy is to:
- Sort all available ones by their distance from position
i
- Select the
remaining_needed
closest ones - Calculate the actual cost for only those selected ones
Corrected Code Segment:
if left_count + right_count >= remaining_needed:
# Collect all ones with their distances
ones_with_dist = []
# Add ones from left range
for j in range(left_range_start, left_range_end + 1):
if nums[j - 1] == 1:
ones_with_dist.append(i - j) # distance to position i
# Add ones from right range
for j in range(right_range_start, right_range_end + 1):
if nums[j - 1] == 1:
ones_with_dist.append(j - i) # distance to position i
# Sort by distance and take the closest remaining_needed ones
ones_with_dist.sort()
actual_cost = sum(ones_with_dist[:remaining_needed])
min_moves = min(min_moves, moves + actual_cost)
right = mid_radius - 1
2. Alternative Efficient Solution Using Sliding Window
Instead of iterating through positions in the binary search, a more efficient approach maintains sorted positions of all ones and uses a sliding window:
def minimumMoves(self, nums: List[int], k: int, maxChanges: int) -> int:
# Collect positions of all ones
ones_positions = [i for i, val in enumerate(nums) if val == 1]
m = len(ones_positions)
if m == 0:
return 2 * k # All ones must be created using maxChanges
# Prefix sum for efficient range sum calculation
prefix = [0] * (m + 1)
for i in range(m):
prefix[i + 1] = prefix[i] + ones_positions[i]
min_moves = float('inf')
# For each possible collection point
for alice_pos in range(len(nums)):
moves = 0
remaining = k
# Take one at current position if available
if nums[alice_pos] == 1:
remaining -= 1
# Use maxChanges optimally (create adjacent ones)
created = min(remaining, maxChanges)
remaining -= created
moves += created * 2
if remaining == 0:
min_moves = min(min_moves, moves)
continue
# Find the cost to collect 'remaining' closest ones
# Use sliding window on ones_positions
for window_size in range(1, min(remaining, m) + 1):
for start in range(m - window_size + 1):
end = start + window_size
median_idx = (start + end) // 2
median_pos = ones_positions[median_idx]
# Calculate cost to move all ones in window to median_pos
cost = 0
for i in range(start, end):
cost += abs(ones_positions[i] - median_pos)
# Then move from median_pos to alice_pos
cost += abs(median_pos - alice_pos) * window_size
if window_size >= remaining:
min_moves = min(min_moves, moves + cost)
return min_moves
This approach correctly handles partial collection and provides optimal selection of ones to minimize total movement cost.
What is the best way of checking if an element exists in a sorted array once in terms of time complexity? Select the best that applies.
Recommended Readings
Greedy Introduction div class responsive iframe iframe src https www youtube com embed WTslqPbj7I title YouTube video player frameborder 0 allow accelerometer autoplay clipboard write encrypted media gyroscope picture in picture web share allowfullscreen iframe div When do we use greedy Greedy algorithms tend to solve optimization problems Typically they will ask you to calculate the max min of some value Commonly you may see this phrased in the problem as max min longest shortest largest smallest etc These keywords can be identified by just scanning
Prefix Sum The prefix sum is an incredibly powerful and straightforward technique Its primary goal is to allow for constant time range sum queries on an array What is Prefix Sum The prefix sum of an array at index i is the sum of all numbers from index 0 to i By
https assets algo monster cover_photos stack svg Sliding Window Maximum Monotonic Stack We have an array and a sliding window defined by a start index and an end index The sliding window moves from left of the array to right There are always k elements in the window The window
Want a Structured Path to Master System Design Too? Don’t Miss This!