AlgoMaster Logo

Best Sightseeing Pair

mediumFrequency5 min readUpdated June 23, 2026

Understanding the Problem

The score formula values[i] + values[j] + i - j rewards spots with high values but penalizes the distance between them. Two high-value spots on opposite ends of the array can score lower than two moderate spots next to each other.

We need to find the pair (i, j) with i < j that maximizes this score. Checking every pair gives a correct but quadratic solution. The formula can also be regrouped so that each index contributes its own independent term, which reduces the problem to a single pass with a running maximum.

Key Constraints:

  • 2 <= values.length <= 5 * 10^4: an O(n^2) scan checks about 1.25 billion pairs at the upper bound, which is too slow. The target is O(n).
  • 1 <= values[i] <= 1000: every adjacent pair scores values[i] + values[i+1] - 1 >= 1, so the maximum score is always positive and initializing the answer to 0 is safe. Values cap at 1000 and indices at 5 * 10^4, so every intermediate sum fits in a 32-bit integer.

Approach 1: Brute Force

Intuition

Try every pair (i, j) where i < j, compute values[i] + values[j] + i - j, and keep the largest result. Every valid pair gets checked, so correctness is immediate. The cost is the quadratic number of pairs.

Algorithm

  1. Initialize maxScore to 0
  2. For each index i from 0 to n-2:
    • For each index j from i+1 to n-1:
      • Compute score = values[i] + values[j] + i - j
      • Update maxScore if this score is larger
  3. Return maxScore

Example Walkthrough

1Initialize: maxScore=0, check all pairs (i, j) where i < j
0
i
8
1
1
j
2
5
3
2
4
6
1/7

Code

For each index j, the inner loop rescans every previous index i to find its best left partner, even though that best partner changes only when a new element beats the current one. Carrying the best left partner forward in a single variable removes the inner loop entirely.

Approach 2: Decomposition with Running Maximum

Intuition

The score formula mixes the two indices:

values[i] + values[j] + i - j

Regrouping the terms by index separates them:

(values[i] + i) + (values[j] - j)

The score is now the sum of two independent parts. The first part, values[i] + i, depends only on the left spot. The second part, values[j] - j, depends only on the right spot. For any fixed j, maximizing the total score means maximizing values[i] + i among all i < j.

A single left-to-right scan handles that: maintain a running maximum of values[i] + i (the best left partner seen so far). At each position j, combine that running max with values[j] - j to get the best score ending at j, then check whether j itself becomes the new best left partner. The same scan-with-best-earlier-candidate pattern solves Best Time to Buy and Sell Stock.

Algorithm

  1. Initialize maxLeftScore to values[0] + 0 (the values[i] + i contribution of the first spot)
  2. Initialize maxScore to 0
  3. For each index j from 1 to n-1:
    • Compute the score using the best left partner: maxLeftScore + values[j] - j
    • Update maxScore if this is better
    • Update maxLeftScore if values[j] + j is larger (this position becomes the new best left partner for future j's)
  4. Return maxScore

Example Walkthrough

1Initialize: maxLeftScore = values[0]+0 = 8, maxScore = 0
0
8
maxLeft=8
1
1
j
2
5
3
2
4
6
1/6

Code