1064. Fixed Point
Problem Description
You are given an array arr of distinct integers sorted in ascending order. Your task is to find the smallest index i where the value at that index equals the index itself (i.e., arr[i] == i). If no such index exists, return -1.
For example:
- If
arr = [-10, -5, 0, 3, 7], the answer would be3becausearr[3] = 3 - If
arr = [0, 2, 5, 8, 17], the answer would be0becausearr[0] = 0 - If
arr = [-10, -5, 3, 4, 7, 9], the answer would be-1because no index satisfies the condition
The solution uses binary search to efficiently find the answer. The key insight is that since the array is sorted and contains distinct integers:
- If
arr[mid] >= mid, then the fixed point (if it exists) must be at indexmidor to the left ofmid - If
arr[mid] < mid, then the fixed point (if it exists) must be to the right ofmid
This property allows us to eliminate half of the search space in each iteration, achieving O(log n) time complexity instead of the naive O(n) approach of checking every element.
Intuition
The key observation is that we're looking for a point where arr[i] = i. Let's think about what happens as we move through the array:
Since the array contains distinct integers in ascending order, when we examine any index mid:
- If
arr[mid] = mid, we've found a fixed point - If
arr[mid] > mid, the value is "ahead" of its index - If
arr[mid] < mid, the value is "behind" its index
Here's the crucial insight: because the array is sorted and contains distinct integers, the difference arr[i] - i can only increase or stay the same as we move right (it can never decrease by more than 1 per step).
Why? As we move from index i to i+1:
- The index increases by exactly 1
- The array value increases by at least 1 (since values are distinct and sorted)
- Therefore,
(arr[i+1] - (i+1)) >= (arr[i] - i)
This means if at some position mid we have arr[mid] < mid, then for all positions to the left of mid, we'll also have arr[j] < j. There's no way for a value to "catch up" to its index when moving left.
Similarly, if arr[mid] >= mid, there might be a fixed point at mid or to its left, but we need to check the leftmost such position to find the smallest index.
This monotonic property of arr[i] - i allows us to use binary search: we can safely eliminate half of the array in each step based on the comparison at the middle element, reducing our search from O(n) to O(log n).
Learn more about Binary Search patterns.
Solution Implementation
1class Solution:
2 def fixedPoint(self, arr: List[int]) -> int:
3 """
4 Find the smallest index i where arr[i] == i using binary search.
5
6 Args:
7 arr: A sorted array of distinct integers
8
9 Returns:
10 The smallest fixed point index, or -1 if no fixed point exists
11 """
12 # Binary search to find the first index where arr[mid] >= mid
13 # Feasible condition: arr[mid] >= mid
14 # Pattern: [false, false, ..., true, true, true]
15 left, right = 0, len(arr) - 1
16 first_true_index = -1
17
18 while left <= right:
19 mid = (left + right) // 2
20
21 if arr[mid] >= mid:
22 # Feasible: arr[mid] is at or ahead of mid
23 first_true_index = mid
24 right = mid - 1
25 else:
26 # Not feasible: arr[mid] < mid, search right
27 left = mid + 1
28
29 # Check if the found position is actually a fixed point (arr[i] == i)
30 if first_true_index != -1 and arr[first_true_index] == first_true_index:
31 return first_true_index
32 return -1
331class Solution {
2 /**
3 * Finds the smallest index i where arr[i] == i (fixed point).
4 * Uses binary search on a sorted array in ascending order.
5 *
6 * @param arr - sorted array of distinct integers in ascending order
7 * @return the smallest fixed point index, or -1 if none exists
8 */
9 public int fixedPoint(int[] arr) {
10 // Binary search to find the first index where arr[mid] >= mid
11 // Feasible condition: arr[mid] >= mid
12 // Pattern: [false, false, ..., true, true, true]
13 int left = 0;
14 int right = arr.length - 1;
15 int firstTrueIndex = -1;
16
17 while (left <= right) {
18 int mid = left + (right - left) / 2;
19
20 if (arr[mid] >= mid) {
21 // Feasible: arr[mid] is at or ahead of mid
22 firstTrueIndex = mid;
23 right = mid - 1;
24 } else {
25 // Not feasible: arr[mid] < mid, search right
26 left = mid + 1;
27 }
28 }
29
30 // Check if the found position is actually a fixed point (arr[i] == i)
31 if (firstTrueIndex != -1 && arr[firstTrueIndex] == firstTrueIndex) {
32 return firstTrueIndex;
33 }
34 return -1;
35 }
36}
371class Solution {
2public:
3 /**
4 * Find the smallest index i where arr[i] == i (fixed point)
5 * @param arr - sorted distinct integers array
6 * @return smallest fixed point index, or -1 if none exists
7 */
8 int fixedPoint(vector<int>& arr) {
9 // Binary search to find the first index where arr[mid] >= mid
10 // Feasible condition: arr[mid] >= mid
11 // Pattern: [false, false, ..., true, true, true]
12 int left = 0;
13 int right = arr.size() - 1;
14 int firstTrueIndex = -1;
15
16 while (left <= right) {
17 int mid = left + (right - left) / 2;
18
19 if (arr[mid] >= mid) {
20 // Feasible: arr[mid] is at or ahead of mid
21 firstTrueIndex = mid;
22 right = mid - 1;
23 } else {
24 // Not feasible: arr[mid] < mid, search right
25 left = mid + 1;
26 }
27 }
28
29 // Check if the found position is actually a fixed point (arr[i] == i)
30 if (firstTrueIndex != -1 && arr[firstTrueIndex] == firstTrueIndex) {
31 return firstTrueIndex;
32 }
33 return -1;
34 }
35};
361/**
2 * Finds the smallest index i where arr[i] === i (fixed point)
3 * Uses binary search on a sorted array in ascending order
4 * @param arr - A sorted array of distinct integers
5 * @returns The smallest fixed point index, or -1 if none exists
6 */
7function fixedPoint(arr: number[]): number {
8 // Binary search to find the first index where arr[mid] >= mid
9 // Feasible condition: arr[mid] >= mid
10 // Pattern: [false, false, ..., true, true, true]
11 let left = 0;
12 let right = arr.length - 1;
13 let firstTrueIndex = -1;
14
15 while (left <= right) {
16 const mid = Math.floor((left + right) / 2);
17
18 if (arr[mid] >= mid) {
19 // Feasible: arr[mid] is at or ahead of mid
20 firstTrueIndex = mid;
21 right = mid - 1;
22 } else {
23 // Not feasible: arr[mid] < mid, search right
24 left = mid + 1;
25 }
26 }
27
28 // Check if the found position is actually a fixed point (arr[i] == i)
29 if (firstTrueIndex !== -1 && arr[firstTrueIndex] === firstTrueIndex) {
30 return firstTrueIndex;
31 }
32 return -1;
33}
34Solution Approach
The solution implements a binary search algorithm to find the smallest index where arr[i] == i.
Feasible Condition: arr[mid] >= mid - Is the value at mid at or ahead of the index?
This creates a pattern: [false, false, ..., true, true, true]
We want to find the first true index, then verify if it's exactly a fixed point (arr[i] == i, not just arr[i] >= i).
Binary Search Using Template:
-
Initialize:
left = 0,right = len(arr) - 1,first_true_index = -1 -
Loop while
left <= right:- Calculate
mid = (left + right) // 2 - If
arr[mid] >= mid(feasible):- Record
first_true_index = mid - Search left for potentially smaller index:
right = mid - 1
- Record
- Else (not feasible):
- Search right:
left = mid + 1
- Search right:
- Calculate
-
Why this works: When
arr[mid] >= mid:- If
arr[mid] == mid, thenmidcould be our answer, but there might be a smaller fixed point to the left - If
arr[mid] > mid, there still might be a fixed point to the left where the value "catches down" to the index
- If
-
Final check: After the loop, verify if
first_true_index != -1andarr[first_true_index] == first_true_index:- If true, return
first_true_indexas the smallest fixed point - If false, return
-1indicating no fixed point exists
- If true, return
The algorithm guarantees finding the smallest index because we continue searching left (right = mid - 1) even after finding a feasible position.
Time Complexity: O(log n) due to binary search
Space Complexity: O(1) as we only use a constant amount of extra space
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 the algorithm with arr = [-10, -5, 0, 3, 7].
We're looking for the smallest index i where arr[i] == i.
Initial Setup:
left = 0,right = 4,first_true_index = -1- Feasible condition:
arr[mid] >= mid - Array visualization with indices:
Index: 0 1 2 3 4 Value: -10 -5 0 3 7
Iteration 1:
left = 0,right = 4mid = (0 + 4) // 2 = 2- Check
arr[2] = 0 >= mid = 2? →0 >= 2is FALSE - Not feasible, search right:
left = 3
Iteration 2:
left = 3,right = 4mid = (3 + 4) // 2 = 3- Check
arr[3] = 3 >= mid = 3? →3 >= 3is TRUE - Feasible! Record
first_true_index = 3 - Search left for smaller:
right = 2
Iteration 3:
left = 3,right = 2left > right, loop terminates
Final Check:
first_true_index = 3- Check if
arr[3] == 3? → Yes! - Return
3
The algorithm correctly identifies that index 3 is the smallest (and only) index where the value equals the index.
Why Binary Search Works Here: Notice how at each step, we eliminated half of the search space:
- When
arr[2] = 0 < 2, we knew indices 0, 1, 2 couldn't be fixed points (values are too small) - When
arr[3] = 3 >= 3, we found our potential answer and continued searching left for any smaller fixed point
The sorted and distinct nature of the array ensures that once values fall behind indices (arr[i] < i), they can never catch up when moving left, making binary search possible.
Time and Space Complexity
Time Complexity: O(log n)
The algorithm uses binary search to find the fixed point (where arr[i] == i). In each iteration, the search space is halved by comparing the middle element with its index:
- If
arr[mid] >= mid, the fixed point (if it exists) must be in the left half includingmid, so we setright = mid - If
arr[mid] < mid, the fixed point must be in the right half, so we setleft = mid + 1
Since the search space is reduced by half in each iteration, and we continue until left >= right, the total number of iterations is O(log n) where n is the length of the array.
Space Complexity: O(1)
The algorithm only uses a constant amount of extra space for the variables left, right, and mid. No additional data structures are created that depend on the input size, making the space complexity constant.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Using the Wrong Binary Search Template
The Pitfall: Using while left < right with right = mid instead of the standard template.
# Alternative template (not recommended) while left < right: mid = (left + right) >> 1 if arr[mid] >= mid: right = mid else: left = mid + 1 return left if arr[left] == left else -1
The Solution: Use the standard template with while left <= right and first_true_index:
first_true_index = -1 while left <= right: mid = (left + right) // 2 if arr[mid] >= mid: first_true_index = mid right = mid - 1 else: left = mid + 1 return first_true_index if first_true_index != -1 and arr[first_true_index] == first_true_index else -1
2. Returning Early When arr[mid] == mid
The Pitfall: Immediately returning mid when arr[mid] == mid is found.
# INCORRECT approach while left <= right: mid = (left + right) // 2 if arr[mid] == mid: return mid # Wrong! This might not be the smallest index
Why it's wrong: This fails to find the smallest index. For arr = [0, 1, 5, 8], if we check mid = 1 and find arr[1] == 1, we'd return 1, missing index 0.
The Solution: Always search left (right = mid - 1) when feasible to find the smallest index.
3. Forgetting the Final Validation
The Pitfall: Not checking if first_true_index is actually a fixed point.
# INCORRECT approach return first_true_index # Wrong! arr[first_true_index] might be > first_true_index
Why it's wrong: The feasible condition is arr[mid] >= mid, not arr[mid] == mid. The first feasible index might have arr[i] > i, not arr[i] == i.
The Solution: Always validate:
if first_true_index != -1 and arr[first_true_index] == first_true_index: return first_true_index return -1
4. Integer Overflow in Mid Calculation
The Pitfall: Using mid = (left + right) / 2 could cause overflow in languages with fixed integer sizes.
The Solution: Use mid = left + (right - left) / 2. Python handles large integers gracefully, but this is good practice for portable code.
Which algorithm should you use to find a node that is close to the root of the tree?
Recommended Readings
https assets algo monster cover_photos Binary_Search svg Binary Search Intuition Binary search is an efficient array search algorithm It works by narrowing down the search range by half each time If you have looked up a word in a physical dictionary you've already used binary search in real life Let's
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion If you prefer videos here's a video that explains recursion in a fun and easy way Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask him
Want a Structured Path to Master System Design Too? Don’t Miss This!