Search Insert Position - Complete Solution Guide
Search Insert Position is LeetCode problem 35, a Easy level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
Given a sorted array of distinct integers and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order. You must write an algorithm with O(log n) runtime complexity. Example 1: Input: nums = [1,3,5,6], target = 5 Output: 2 Example 2: Input: nums = [1,3,5,6], target = 2 Output: 1 Example 3: Input: nums = [1,3,5,6], target = 7 Output: 4 Constraints: 1 <= nums.length <= 10 4 -10 4 <= nums[i] <= 10 4 nums contains distinct value
Detailed Explanation
This problem asks us to locate a specific `target` value within a `sorted` array of `distinct` integers. The twist isn't just finding it; if the `target` isn't present, we need to determine the index where it *would* be inserted to maintain the array's sorted order. For example, if we have `nums = [1,3,5,6]` and `target = 5`, the output is `2` because `5` is at index `2`. However, if `target = 2`, the output should be `1` since `2` would fit perfectly between `1` (at index `0`) and `3` (at index `1`). Similarly, if `target = 7`, which is larger than all elements, it should be inserted at the very end, resulting in an output of `4` (which is `len(nums)`). The crucial constraint is the `O(log n)` runtime complexity. This immediately signals that a linear scan, while simple, is not sufficient for larger inputs. The sorted nature of the input array combined with the logarithmic time requirement points directly towards a binary search approach, but we need to adapt it slightly to handle the 'insertion point' scenario gracefully.
Solution Approach
The solution employs a classic binary search algorithm, but it's designed to elegantly handle both finding the target and identifying its insertion point. We initialize two pointers, `l` (left) at `0` and `r` (right) at `len(nums) - 1`, defining our search space. Inside a `while l <= r` loop, we calculate the `mid` index. If `nums[mid]` matches our `target`, we've found it and return `mid`. If `nums[mid]` is less than `target`, it means the `target` must lie to the right of `mid` (if it exists at all), so we update `l = mid + 1`. Conversely, if `nums[mid]` is greater than `target`, the `target` must be to the left of `mid` (or `mid` itself is a potential insertion point), so we update `r = mid - 1`. The magic happens when the loop terminates. At this point, `l` will always point to the correct insertion index. If the `target` was found, we would have returned early. If not, `l` has pushed past `r`, and it will be precisely the index where the `target` should be inserted to maintain order. Think of `l` as tracking the first element that is greater than or equal to `target` throughout the search; when the loop ends, this `l` is the ultimate candidate.
Step-by-Step Algorithm
- Step 1: Initialize `left` to 0 and `right` to `nums.length - 1`.
- Step 2: While `left` is less than or equal to `right`, calculate the middle index `mid = left + (right - left) / 2`. This prevents potential integer overflow.
- Step 3: If `nums[mid]` equals the `target`, return `mid`.
- Step 4: If `nums[mid]` is less than `target`, update `left` to `mid + 1` (search in the right half).
- Step 5: Otherwise, update `right` to `mid - 1` (search in the left half).
- Step 6: After the loop, return `left`. This index represents the insertion point if the target is not found.
Key Insights
- The `O(log n)` runtime constraint, coupled with the sorted input array, makes binary search the only viable algorithm. A linear scan would fall short of this performance target.
- The elegance of this binary search implementation lies in how `l` (the left pointer) naturally converges to the correct insertion index when the target is not found. When the `while l <= r` loop finally breaks, `l` will invariably point to the first element that is greater than or equal to the `target`. If no such element exists (i.e., `target` is greater than all elements), `l` will be `len(nums)`, which is the correct insertion index at the end of the array.
- The `mid` calculation `(l + r) // 2` and the update rules `l = mid + 1` and `r = mid - 1` are robust. They ensure that the search space is correctly narrowed down, and crucially, `l` always represents the *lower bound* of where `target` *could* be inserted, eventually settling on the precise spot whether `target` is present or not. This avoids the need for a separate post-loop check to determine the insertion point.
Complexity Analysis
Time Complexity: O(log n)
Space Complexity: O(1)
Topics
This problem involves: Array, Binary Search.
Companies
Asked at: Adobe, Amazon, Apple, Bloomberg, Cognizant, Instacart, Meta, Microsoft, Uber, Yahoo, Zoho.