Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Move from brute-force thinking to an efficient approach using array strategy.
You are given two 1-indexed integer arrays, nums and, changeIndices, having lengths n and m, respectively.
Initially, all indices in nums are unmarked. Your task is to mark all indices in nums.
In each second, s, in order from 1 to m (inclusive), you can perform one of the following operations:
i in the range [1, n] and decrement nums[i] by 1.nums[changeIndices[s]] is equal to 0, mark the index changeIndices[s].Return an integer denoting the earliest second in the range [1, m] when all indices in nums can be marked by choosing operations optimally, or -1 if it is impossible.
Example 1:
Input: nums = [2,2,0], changeIndices = [2,2,2,2,3,2,2,1] Output: 8 Explanation: In this example, we have 8 seconds. The following operations can be performed to mark all indices: Second 1: Choose index 1 and decrement nums[1] by one. nums becomes [1,2,0]. Second 2: Choose index 1 and decrement nums[1] by one. nums becomes [0,2,0]. Second 3: Choose index 2 and decrement nums[2] by one. nums becomes [0,1,0]. Second 4: Choose index 2 and decrement nums[2] by one. nums becomes [0,0,0]. Second 5: Mark the index changeIndices[5], which is marking index 3, since nums[3] is equal to 0. Second 6: Mark the index changeIndices[6], which is marking index 2, since nums[2] is equal to 0. Second 7: Do nothing. Second 8: Mark the index changeIndices[8], which is marking index 1, since nums[1] is equal to 0. Now all indices have been marked. It can be shown that it is not possible to mark all indices earlier than the 8th second. Hence, the answer is 8.
Example 2:
Input: nums = [1,3], changeIndices = [1,1,1,2,1,1,1] Output: 6 Explanation: In this example, we have 7 seconds. The following operations can be performed to mark all indices: Second 1: Choose index 2 and decrement nums[2] by one. nums becomes [1,2]. Second 2: Choose index 2 and decrement nums[2] by one. nums becomes [1,1]. Second 3: Choose index 2 and decrement nums[2] by one. nums becomes [1,0]. Second 4: Mark the index changeIndices[4], which is marking index 2, since nums[2] is equal to 0. Second 5: Choose index 1 and decrement nums[1] by one. nums becomes [0,0]. Second 6: Mark the index changeIndices[6], which is marking index 1, since nums[1] is equal to 0. Now all indices have been marked. It can be shown that it is not possible to mark all indices earlier than the 6th second. Hence, the answer is 6.
Example 3:
Input: nums = [0,1], changeIndices = [2,2,2] Output: -1 Explanation: In this example, it is impossible to mark all indices because index 1 isn't in changeIndices. Hence, the answer is -1.
Constraints:
1 <= n == nums.length <= 20000 <= nums[i] <= 1091 <= m == changeIndices.length <= 20001 <= changeIndices[i] <= nProblem summary: You are given two 1-indexed integer arrays, nums and, changeIndices, having lengths n and m, respectively. Initially, all indices in nums are unmarked. Your task is to mark all indices in nums. In each second, s, in order from 1 to m (inclusive), you can perform one of the following operations: Choose an index i in the range [1, n] and decrement nums[i] by 1. If nums[changeIndices[s]] is equal to 0, mark the index changeIndices[s]. Do nothing. Return an integer denoting the earliest second in the range [1, m] when all indices in nums can be marked by choosing operations optimally, or -1 if it is impossible.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array · Binary Search
[2,2,0] [2,2,2,2,3,2,2,1]
[1,3] [1,1,1,2,1,1,1]
[0,1] [2,2,2]
Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #3048: Earliest Second to Mark Indices I
class Solution {
private int[] nums;
private int[] changeIndices;
public int earliestSecondToMarkIndices(int[] nums, int[] changeIndices) {
this.nums = nums;
this.changeIndices = changeIndices;
int m = changeIndices.length;
int l = 1, r = m + 1;
while (l < r) {
int mid = (l + r) >> 1;
if (check(mid)) {
r = mid;
} else {
l = mid + 1;
}
}
return l > m ? -1 : l;
}
private boolean check(int t) {
int[] last = new int[nums.length + 1];
for (int s = 0; s < t; ++s) {
last[changeIndices[s]] = s;
}
int decrement = 0;
int marked = 0;
for (int s = 0; s < t; ++s) {
int i = changeIndices[s];
if (last[i] == s) {
if (decrement < nums[i - 1]) {
return false;
}
decrement -= nums[i - 1];
++marked;
} else {
++decrement;
}
}
return marked == nums.length;
}
}
// Accepted solution for LeetCode #3048: Earliest Second to Mark Indices I
func earliestSecondToMarkIndices(nums []int, changeIndices []int) int {
n, m := len(nums), len(changeIndices)
l := sort.Search(m+1, func(t int) bool {
last := make([]int, n+1)
for s, i := range changeIndices[:t] {
last[i] = s
}
decrement, marked := 0, 0
for s, i := range changeIndices[:t] {
if last[i] == s {
if decrement < nums[i-1] {
return false
}
decrement -= nums[i-1]
marked++
} else {
decrement++
}
}
return marked == n
})
if l > m {
return -1
}
return l
}
# Accepted solution for LeetCode #3048: Earliest Second to Mark Indices I
class Solution:
def earliestSecondToMarkIndices(
self, nums: List[int], changeIndices: List[int]
) -> int:
def check(t: int) -> bool:
decrement = 0
marked = 0
last = {i: s for s, i in enumerate(changeIndices[:t])}
for s, i in enumerate(changeIndices[:t]):
if last[i] == s:
if decrement < nums[i - 1]:
return False
decrement -= nums[i - 1]
marked += 1
else:
decrement += 1
return marked == len(nums)
m = len(changeIndices)
l = bisect_left(range(1, m + 2), True, key=check) + 1
return -1 if l > m else l
// Accepted solution for LeetCode #3048: Earliest Second to Mark Indices I
// Rust example auto-generated from java reference.
// Replace the signature and local types with the exact LeetCode harness for this problem.
impl Solution {
pub fn rust_example() {
// Port the logic from the reference block below.
}
}
// Reference (java):
// // Accepted solution for LeetCode #3048: Earliest Second to Mark Indices I
// class Solution {
// private int[] nums;
// private int[] changeIndices;
//
// public int earliestSecondToMarkIndices(int[] nums, int[] changeIndices) {
// this.nums = nums;
// this.changeIndices = changeIndices;
// int m = changeIndices.length;
// int l = 1, r = m + 1;
// while (l < r) {
// int mid = (l + r) >> 1;
// if (check(mid)) {
// r = mid;
// } else {
// l = mid + 1;
// }
// }
// return l > m ? -1 : l;
// }
//
// private boolean check(int t) {
// int[] last = new int[nums.length + 1];
// for (int s = 0; s < t; ++s) {
// last[changeIndices[s]] = s;
// }
// int decrement = 0;
// int marked = 0;
// for (int s = 0; s < t; ++s) {
// int i = changeIndices[s];
// if (last[i] == s) {
// if (decrement < nums[i - 1]) {
// return false;
// }
// decrement -= nums[i - 1];
// ++marked;
// } else {
// ++decrement;
// }
// }
// return marked == nums.length;
// }
// }
// Accepted solution for LeetCode #3048: Earliest Second to Mark Indices I
function earliestSecondToMarkIndices(nums: number[], changeIndices: number[]): number {
const [n, m] = [nums.length, changeIndices.length];
let [l, r] = [1, m + 1];
const check = (t: number): boolean => {
const last: number[] = Array(n + 1).fill(0);
for (let s = 0; s < t; ++s) {
last[changeIndices[s]] = s;
}
let [decrement, marked] = [0, 0];
for (let s = 0; s < t; ++s) {
const i = changeIndices[s];
if (last[i] === s) {
if (decrement < nums[i - 1]) {
return false;
}
decrement -= nums[i - 1];
++marked;
} else {
++decrement;
}
}
return marked === n;
};
while (l < r) {
const mid = (l + r) >> 1;
if (check(mid)) {
r = mid;
} else {
l = mid + 1;
}
}
return l > m ? -1 : l;
}
Use this to step through a reusable interview workflow for this problem.
Check every element from left to right until we find the target or exhaust the array. Each comparison is O(1), and we may visit all n elements, giving O(n). No extra space needed.
Each comparison eliminates half the remaining search space. After k comparisons, the space is n/2ᵏ. We stop when the space is 1, so k = log₂ n. No extra memory needed — just two pointers (lo, hi).
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Wrong move: Setting `lo = mid` or `hi = mid` can stall and create an infinite loop.
Usually fails on: Two-element ranges never converge.
Fix: Use `lo = mid + 1` or `hi = mid - 1` where appropriate.