Quick Overview

Choose nonadjacent indices for one common nonnegative increment to make an array nondecreasing, or determine that no operation can succeed.

Find the Minimum Shared Increment on Nonadjacent Array Positions

Company: IBM

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: easy

Interview Round: Online Assessment

You may perform at most one operation on an integer array. Choose a set of pairwise nonadjacent indices and add the same nonnegative integer x to every chosen element. Find the smallest x that can make the entire array nondecreasing, or return -1 if no such operation exists. ### Function Signature `minimum_nondecreasing_increment(values: list[int]) -> int` ### Rules - Chosen indices are pairwise nonadjacent: no two chosen indices differ by one. - The same x must be used at every chosen index. - Unchosen elements do not change. - Nondecreasing means each element is at most the next one after the operation. - If the array is already nondecreasing, return 0. This includes an empty array or one-element array under the exercise's explicit boundary convention. - There is no requirement to choose an index when no change is needed. ### Constraints - `0 <= len(values) <= 200000`. - `-1000000000 <= values[i] <= 1000000000`. - x is an integer and has no additional artificial upper bound. - Do not mutate the input. ### Examples Input: `values = [3,1,4,2]` Output: `2` Choose indices 1 and 3 to obtain `[3,3,4,4]`. Input: `values = [3,1,2]` Output: `-1` Raising index 1 enough to reach 3 makes it exceed index 2, and indices 1 and 2 cannot both be selected. Input: `values = [1,2,2,5]` Output: `0` Input: `values = []` Output: `0`

Overview: Choose nonadjacent indices for one common nonnegative increment to make an array nondecreasing, or determine that no operation can succeed.

You are given an integer array `values`. You may perform at most one operation on it. The operation works like this: choose a set of pairwise nonadjacent indices (no two chosen indices differ by one), pick a single nonnegative integer `x`, and add that same `x` to every chosen element. Elements at indices you did not choose are left unchanged. You are never required to choose an index, so choosing nothing is allowed. An array is nondecreasing when every element is at most the element that follows it. Return the smallest nonnegative integer `x` for which some such choice of nonadjacent indices makes the whole array nondecreasing, or return `-1` if no choice of indices and `x` can do it. If the array is already nondecreasing, return `0`; by this exercise's explicit boundary convention that includes the empty array and any one-element array. Do not mutate the input array. Example 1: Input: `values = [3, 1, 4, 2]` Output: `2` Choosing the nonadjacent indices 1 and 3 with x = 2 gives `[3, 3, 4, 4]`, which is nondecreasing. x = 1 is not enough, because 1 + 1 = 2 is still below values[0] = 3. Example 2: Input: `values = [3, 1, 2]` Output: `-1` Index 1 would have to be raised to at least 3 to catch up with values[0] = 3, but then it exceeds values[2] = 2, and indices 1 and 2 are adjacent, so they cannot both be chosen. The answer can be as large as 2,000,000,000 and intermediate quantities such as `values[i] + x` can reach 3,000,000,000, which is larger than 2^31 - 1, so use 64-bit integers (`long` in Java, `long long` in C++).

Constraints

  • 0 <= len(values) <= 200000
  • -1000000000 <= values[i] <= 1000000000
  • x is an integer, must be nonnegative, and has no additional artificial upper bound
  • Chosen indices are pairwise nonadjacent: no two chosen indices differ by one, and the same x is added at every chosen index
  • Unchosen elements do not change, and there is no requirement to choose any index
  • Return 0 when the array is already nondecreasing, including the empty array and any one-element array
  • Do not mutate the input array
  • The answer can reach 2000000000 and values[i] + x can reach 3000000000, which exceeds 2^31 - 1, so use 64-bit integers (long in Java, long long in C++)

Examples

Input: ([],)

Expected Output: 0

Explanation: The empty array is nondecreasing by the stated boundary convention, so no operation is needed.

Input: ([7],)

Expected Output: 0

Explanation: A one-element array is nondecreasing by the stated boundary convention.

Hints

  1. Consider one adjacent pair at a time and remember that its two positions can never both be chosen, so a pair admits only three situations: neither position raised, the left one raised, or the right one raised.
  2. When values[i] > values[i + 1], ask which of the two positions could possibly be raised given that x is nonnegative; the answer leaves you no freedom at either position.
  3. Each adjacent pair turns into either a lower bound or an upper bound on the single shared x; the operation exists only when all of those bounds can hold simultaneously.

Loading coding console...

Show the approach

Approach

Examine every adjacent pair (i, i + 1) on its own. Because chosen indices are pairwise nonadjacent, at most one of the two positions of a pair can be raised, which leaves exactly three possibilities for that pair:

  • neither is raised: the pair is satisfied only if values[i] <= values[i + 1];
  • index i is raised: needs values[i] + x <= values[i + 1], i.e. x <= values[i + 1] - values[i];
  • index i + 1 is raised: needs values[i] <= values[i + 1] + x, i.e. x >= values[i] - values[i + 1].

If values[i] > values[i + 1] (a descent), the first option fails outright and the second would need a negative x, so index i + 1 MUST be raised and index i MUST NOT be. That forcing determines everything:

  1. First pass: set raised[i + 1] = True for every descent at pair (i, i + 1). If some index is both marked and the left end of a descent (raised[i] is True and values[i] > values[i + 1]) it is simultaneously required to be raised and required not to be, so the answer is -1. This is exactly the situation of two consecutive descents, whose two forced indices would be adjacent.
  2. Otherwise the marked set is itself pairwise nonadjacent and is the only set worth using. Adding any unmarked index never helps: raising an element only tightens the constraint with its right neighbour, while the left-hand constraint it would relax already holds (otherwise that index would have been marked).
  3. Second pass: collect the bounds. Every descent contributes a lower bound x >= values[i] - values[i + 1]; take the maximum as low. Every marked index i that still has a right neighbour contributes an upper bound x <= values[i + 1] - values[i]; take the minimum as high.
  4. If there was no descent, low stays 0 and the array is already nondecreasing, so return 0. Otherwise return low when there is no upper bound or low <= high; return -1 when low > high.

Invariant: after the first pass, raised[] is precisely the set of indices that EVERY valid solution must raise, so the set of feasible x is exactly the integers in the interval [low, high] (with high = +infinity when no marked index has a right neighbour). The smallest feasible x is therefore low whenever that interval is nonempty.

Edge cases: arrays of length 0 or 1 are nondecreasing and return 0; a descent in the final pair leaves its forced index without a right neighbour, so it contributes no upper bound; an all-equal array has no descent and returns 0; a forced index may need to land exactly on its right neighbour (low == high), which is still valid because nondecreasing allows equality. With values bounded by 1e9 in absolute value, low can be 2000000000 and values[i] + x can reach 3000000000, so 64-bit arithmetic is used in Java and C++. The input array is only read, never mutated.

Time complexity:
O(n)
Space complexity:
O(n)