Bird
Raised Fist0
Interview Prepmodified-binary-searcheasyAmazonGoogle

Search Insert Position

Choose your preparation mode4 modes available
🎯
Search Insert Position
easyBINARY_SEARCHAmazonGoogle

Imagine you have a sorted list of book titles and want to find where to insert a new title so the list remains sorted.

💡 This problem is about finding the correct position to insert a target value in a sorted array. Beginners often struggle because they try linear search or don't understand how binary search can be adapted to find insertion points, not just exact matches.
📋
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.

1 ≤ nums.length ≤ 10^5-10^4 ≤ nums[i], target ≤ 10^4nums contains distinct values sorted in ascending order
💡
Example
Input"nums = [1,3,5,6], target = 5"
Output2

Target 5 is found at index 2.

Input"nums = [1,3,5,6], target = 2"
Output1

Target 2 is not found; it would be inserted at index 1 to keep array sorted.

Input"nums = [1,3,5,6], target = 7"
Output4

Target 7 is greater than all elements, so insert at the end (index 4).

Input"nums = [1,3,5,6], target = 0"
Output0

Target 0 is smaller than all elements, so insert at the beginning (index 0).

  • Single element array, target less than element → insert at 0
  • Single element array, target greater than element → insert at 1
  • Target equals first element → return 0
  • Target equals last element → return last index
⚠️
Common Mistakes
Using mid = (left + right) / 2 without floor or integer division

In some languages, this causes float index or wrong mid calculation

✅ Use integer division or floor function to get integer mid

Not updating left or right pointers correctly (off-by-one errors)

Infinite loop or incorrect insertion index

✅ Ensure left = mid + 1 or right = mid - 1 depending on comparison

Returning right instead of left after loop ends

Wrong insertion index returned

✅ Return left pointer as insertion position after loop

Not handling empty array input

Code may crash or return invalid index

✅ Check if array is empty and return 0 as insertion position

Using linear search in large arrays during interview

Inefficient solution leading to time limit exceeded

✅ Use binary search to achieve O(log n) time

🧠
Brute Force (Linear Search)
💡 This approach exists to build intuition by checking each element one by one. It is simple but inefficient for large arrays, highlighting why binary search is needed.

Intuition

Scan the array from left to right and find the first element greater than or equal to the target. The index of this element is the insertion position.

Algorithm

  1. Start from the first element and iterate through the array.
  2. For each element, check if it is greater than or equal to the target.
  3. If yes, return the current index as the insertion position.
  4. If no element is greater or equal, return the length of the array.
💡 The algorithm is straightforward but inefficient because it checks every element even if the array is sorted.
</>
Code
def searchInsert(nums, target):
    for i in range(len(nums)):
        if nums[i] >= target:
            return i
    return len(nums)

# Driver code
if __name__ == '__main__':
    print(searchInsert([1,3,5,6], 5))  # Output: 2
    print(searchInsert([1,3,5,6], 2))  # Output: 1
    print(searchInsert([1,3,5,6], 7))  # Output: 4
    print(searchInsert([1,3,5,6], 0))  # Output: 0
Line Notes
for i in range(len(nums))Iterate over each index to check elements sequentially
if nums[i] >= targetCheck if current element is the insertion point or exact match
return iReturn index immediately when insertion point found
return len(nums)If no element is greater or equal, insert at the end
public class Solution {
    public static int searchInsert(int[] nums, int target) {
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] >= target) {
                return i;
            }
        }
        return nums.length;
    }

    public static void main(String[] args) {
        System.out.println(searchInsert(new int[]{1,3,5,6}, 5)); // 2
        System.out.println(searchInsert(new int[]{1,3,5,6}, 2)); // 1
        System.out.println(searchInsert(new int[]{1,3,5,6}, 7)); // 4
        System.out.println(searchInsert(new int[]{1,3,5,6}, 0)); // 0
    }
}
Line Notes
for (int i = 0; i < nums.length; i++)Loop through array elements sequentially
if (nums[i] >= target)Check if current element is suitable insertion point
return i;Return index immediately when condition met
return nums.length;Insert at end if no element is greater or equal
#include <iostream>
#include <vector>
using namespace std;

int searchInsert(vector<int>& nums, int target) {
    for (int i = 0; i < nums.size(); i++) {
        if (nums[i] >= target) {
            return i;
        }
    }
    return nums.size();
}

int main() {
    vector<int> nums1 = {1,3,5,6};
    cout << searchInsert(nums1, 5) << endl; // 2
    cout << searchInsert(nums1, 2) << endl; // 1
    cout << searchInsert(nums1, 7) << endl; // 4
    cout << searchInsert(nums1, 0) << endl; // 0
    return 0;
}
Line Notes
for (int i = 0; i < nums.size(); i++)Sequentially check each element in vector
if (nums[i] >= target)Find first element not less than target
return i;Return insertion index immediately
return nums.size();If none found, insert at end
function searchInsert(nums, target) {
    for (let i = 0; i < nums.length; i++) {
        if (nums[i] >= target) {
            return i;
        }
    }
    return nums.length;
}

// Test cases
console.log(searchInsert([1,3,5,6], 5)); // 2
console.log(searchInsert([1,3,5,6], 2)); // 1
console.log(searchInsert([1,3,5,6], 7)); // 4
console.log(searchInsert([1,3,5,6], 0)); // 0
Line Notes
for (let i = 0; i < nums.length; i++)Loop through array elements one by one
if (nums[i] >= target)Check if current element is insertion point
return i;Return index immediately when found
return nums.length;Insert at end if no suitable element found
⏱
Complexity
TimeO(n)
SpaceO(1)

We scan the array once until we find the insertion point or reach the end, so time is linear in array size.

💡 For n=100, this means up to 100 comparisons, which is inefficient for large arrays.
Interview Verdict: Accepted but inefficient for large inputs

This approach works but is too slow for large arrays, motivating binary search.

🧠
Binary Search (Iterative)
💡 Binary search leverages the sorted property to find the insertion point in O(log n) time, which is much faster than linear search.

Intuition

Use two pointers to narrow down the search space by comparing the middle element with the target, adjusting pointers until the insertion position is found.

Algorithm

  1. Initialize left and right pointers to start and end of array.
  2. While left <= right, compute mid index.
  3. If nums[mid] equals target, return mid.
  4. If nums[mid] < target, move left to mid + 1.
  5. Else move right to mid - 1.
  6. Return left as the insertion position after loop ends.
💡 The key is that left ends up at the correct insertion point when the loop finishes.
</>
Code
def searchInsert(nums, target):
    left, right = 0, len(nums) - 1
    while left <= right:
        mid = (left + right) // 2
        if nums[mid] == target:
            return mid
        elif nums[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
    return left

# Driver code
if __name__ == '__main__':
    print(searchInsert([1,3,5,6], 5))  # 2
    print(searchInsert([1,3,5,6], 2))  # 1
    print(searchInsert([1,3,5,6], 7))  # 4
    print(searchInsert([1,3,5,6], 0))  # 0
Line Notes
left, right = 0, len(nums) - 1Initialize search boundaries to entire array
while left <= right:Loop until search space is exhausted
mid = (left + right) // 2Find middle index to check
if nums[mid] == target:If found target, return immediately
elif nums[mid] < target:Target is in right half, move left pointer
else: right = mid - 1Target in left half, move right pointer
return leftLeft pointer is insertion position after loop
public class Solution {
    public static int searchInsert(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (nums[mid] == target) {
                return mid;
            } else if (nums[mid] < target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return left;
    }

    public static void main(String[] args) {
        System.out.println(searchInsert(new int[]{1,3,5,6}, 5)); // 2
        System.out.println(searchInsert(new int[]{1,3,5,6}, 2)); // 1
        System.out.println(searchInsert(new int[]{1,3,5,6}, 7)); // 4
        System.out.println(searchInsert(new int[]{1,3,5,6}, 0)); // 0
    }
}
Line Notes
int left = 0, right = nums.length - 1;Set initial search boundaries
while (left <= right)Continue while search space valid
int mid = left + (right - left) / 2;Calculate mid to avoid overflow
if (nums[mid] == target)Return mid if target found
else if (nums[mid] < target)Search right half if target greater
else { right = mid - 1; }Search left half if target smaller
return left;Left is insertion index after loop
#include <iostream>
#include <vector>
using namespace std;

int searchInsert(vector<int>& nums, int target) {
    int left = 0, right = nums.size() - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) {
            return mid;
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return left;
}

int main() {
    vector<int> nums1 = {1,3,5,6};
    cout << searchInsert(nums1, 5) << endl; // 2
    cout << searchInsert(nums1, 2) << endl; // 1
    cout << searchInsert(nums1, 7) << endl; // 4
    cout << searchInsert(nums1, 0) << endl; // 0
    return 0;
}
Line Notes
int left = 0, right = nums.size() - 1;Initialize search boundaries
while (left <= right)Loop while search space exists
int mid = left + (right - left) / 2;Calculate mid index safely
if (nums[mid] == target)Return mid if target found
else if (nums[mid] < target)Move left pointer if target greater
else { right = mid - 1; }Move right pointer if target smaller
return left;Left pointer is insertion position
function searchInsert(nums, target) {
    let left = 0, right = nums.length - 1;
    while (left <= right) {
        let mid = Math.floor((left + right) / 2);
        if (nums[mid] === target) {
            return mid;
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return left;
}

// Test cases
console.log(searchInsert([1,3,5,6], 5)); // 2
console.log(searchInsert([1,3,5,6], 2)); // 1
console.log(searchInsert([1,3,5,6], 7)); // 4
console.log(searchInsert([1,3,5,6], 0)); // 0
Line Notes
let left = 0, right = nums.length - 1;Initialize search boundaries
while (left <= right)Loop while search space is valid
let mid = Math.floor((left + right) / 2);Calculate middle index
if (nums[mid] === target)Return mid if target found
else if (nums[mid] < target)Search right half if target greater
else { right = mid - 1; }Search left half if target smaller
return left;Left pointer is insertion position after loop
⏱
Complexity
TimeO(log n)
SpaceO(1)

Binary search halves the search space each iteration, so it runs in logarithmic time.

💡 For n=100, this means about 7 comparisons, much faster than linear search.
Interview Verdict: Accepted and optimal for this problem

This is the standard approach expected in interviews for sorted array search problems.

🧠
Binary Search (Recursive)
💡 This approach uses recursion to implement binary search, which some find more intuitive. It also achieves O(log n) time but uses extra stack space.

Intuition

Recursively divide the array into halves, checking the middle element and searching the appropriate half until the insertion point is found.

Algorithm

  1. Define a recursive function with left and right pointers.
  2. If left > right, return left as insertion position.
  3. Calculate mid index.
  4. If nums[mid] equals target, return mid.
  5. If nums[mid] < target, recurse on right half (mid+1 to right).
  6. Else recurse on left half (left to mid-1).
💡 The base case returns the insertion point when search space is empty.
</>
Code
def searchInsert(nums, target):
    def binary_search(left, right):
        if left > right:
            return left
        mid = (left + right) // 2
        if nums[mid] == target:
            return mid
        elif nums[mid] < target:
            return binary_search(mid + 1, right)
        else:
            return binary_search(left, mid - 1)
    return binary_search(0, len(nums) - 1)

# Driver code
if __name__ == '__main__':
    print(searchInsert([1,3,5,6], 5))  # 2
    print(searchInsert([1,3,5,6], 2))  # 1
    print(searchInsert([1,3,5,6], 7))  # 4
    print(searchInsert([1,3,5,6], 0))  # 0
Line Notes
def binary_search(left, right):Helper function to perform recursive binary search
if left > right:Base case: search space empty, return insertion point
mid = (left + right) // 2Calculate middle index
if nums[mid] == target:Return mid if target found
elif nums[mid] < target:Recurse on right half if target greater
else:Recurse on left half if target smaller
public class Solution {
    public static int searchInsert(int[] nums, int target) {
        return binarySearch(nums, target, 0, nums.length - 1);
    }

    private static int binarySearch(int[] nums, int target, int left, int right) {
        if (left > right) {
            return left;
        }
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) {
            return mid;
        } else if (nums[mid] < target) {
            return binarySearch(nums, target, mid + 1, right);
        } else {
            return binarySearch(nums, target, left, mid - 1);
        }
    }

    public static void main(String[] args) {
        System.out.println(searchInsert(new int[]{1,3,5,6}, 5)); // 2
        System.out.println(searchInsert(new int[]{1,3,5,6}, 2)); // 1
        System.out.println(searchInsert(new int[]{1,3,5,6}, 7)); // 4
        System.out.println(searchInsert(new int[]{1,3,5,6}, 0)); // 0
    }
}
Line Notes
return binarySearch(nums, target, 0, nums.length - 1);Start recursive search on full array
if (left > right)Base case: empty search space, return insertion point
int mid = left + (right - left) / 2;Calculate middle index safely
if (nums[mid] == target)Return mid if target found
else if (nums[mid] < target)Recurse on right half if target greater
elseRecurse on left half if target smaller
#include <iostream>
#include <vector>
using namespace std;

int binarySearch(vector<int>& nums, int target, int left, int right) {
    if (left > right) {
        return left;
    }
    int mid = left + (right - left) / 2;
    if (nums[mid] == target) {
        return mid;
    } else if (nums[mid] < target) {
        return binarySearch(nums, target, mid + 1, right);
    } else {
        return binarySearch(nums, target, left, mid - 1);
    }
}

int searchInsert(vector<int>& nums, int target) {
    return binarySearch(nums, target, 0, nums.size() - 1);
}

int main() {
    vector<int> nums1 = {1,3,5,6};
    cout << searchInsert(nums1, 5) << endl; // 2
    cout << searchInsert(nums1, 2) << endl; // 1
    cout << searchInsert(nums1, 7) << endl; // 4
    cout << searchInsert(nums1, 0) << endl; // 0
    return 0;
}
Line Notes
if (left > right)Base case: no elements left, return insertion point
int mid = left + (right - left) / 2;Calculate middle index safely
if (nums[mid] == target)Return mid if target found
else if (nums[mid] < target)Recurse on right half if target greater
elseRecurse on left half if target smaller
return binarySearch(nums, target, 0, nums.size() - 1);Start recursive search
function searchInsert(nums, target) {
    function binarySearch(left, right) {
        if (left > right) {
            return left;
        }
        let mid = Math.floor((left + right) / 2);
        if (nums[mid] === target) {
            return mid;
        } else if (nums[mid] < target) {
            return binarySearch(mid + 1, right);
        } else {
            return binarySearch(left, mid - 1);
        }
    }
    return binarySearch(0, nums.length - 1);
}

// Test cases
console.log(searchInsert([1,3,5,6], 5)); // 2
console.log(searchInsert([1,3,5,6], 2)); // 1
console.log(searchInsert([1,3,5,6], 7)); // 4
console.log(searchInsert([1,3,5,6], 0)); // 0
Line Notes
function binarySearch(left, right)Recursive helper function for binary search
if (left > right)Base case: empty search space, return insertion point
let mid = Math.floor((left + right) / 2);Calculate middle index
if (nums[mid] === target)Return mid if target found
else if (nums[mid] < target)Recurse on right half if target greater
elseRecurse on left half if target smaller
⏱
Complexity
TimeO(log n)
SpaceO(log n)

Recursive calls halve the search space each time, but recursion adds stack space proportional to log n.

💡 For n=100, about 7 recursive calls are made, using extra memory compared to iterative.
Interview Verdict: Accepted, but uses extra stack space

Recursive binary search is elegant but less space efficient than iterative.

📊
All Approaches - One-Glance Tradeoffs
💡 In 95% of interviews, code the iterative binary search approach because it is optimal and space efficient.
ApproachTimeSpaceStack RiskReconstructUse In Interview
1. Brute Force (Linear Search)O(n)O(1)NoN/AMention only - never code for large inputs
2. Binary Search (Iterative)O(log n)O(1)NoN/ACode this approach in interviews
3. Binary Search (Recursive)O(log n)O(log n)Yes (deep recursion)N/AMention or code if interviewer requests recursion
💼
Interview Strategy
💡 Use this guide to understand the problem deeply, practice coding all approaches, and prepare to explain tradeoffs clearly in interviews.

How to Present

Step 1: Clarify problem constraints and examples.Step 2: Explain brute force linear search and its inefficiency.Step 3: Introduce binary search iterative approach as optimal.Step 4: Optionally discuss recursive binary search if asked.Step 5: Code the iterative binary search carefully.Step 6: Test with edge cases and explain complexity.

Time Allocation

Clarify: 2min → Approach: 3min → Code: 8min → Test: 2min. Total ~15min

What the Interviewer Tests

Interviewer tests understanding of binary search, ability to handle edge cases, and code correctness with O(log n) complexity.

Common Follow-ups

  • What if array contains duplicates? → Return first occurrence index or insertion point accordingly.
  • Can you implement using built-in functions? → Use language-specific lower_bound or bisect.
💡 Follow-ups test deeper understanding of binary search variants and language features.
🔍
Pattern Recognition

When to Use

Use this pattern when you have a sorted array and need to find the position of a target or where it should be inserted.

Signature Phrases

return the index if the target is foundreturn the index where it would be if inserted

NOT This Pattern When

Linear search or unsorted array search problems are different and do not use binary search.

Similar Problems

Find First and Last Position of Element in Sorted Array - similar binary search variantFind Minimum in Rotated Sorted Array - uses modified binary searchSearch in Rotated Sorted Array - binary search with rotation handling

Practice

(1/5)
1. You are given an n x n matrix where each row and each column is sorted in ascending order. You need to find the kth smallest element in the matrix efficiently. Which of the following approaches guarantees the optimal time complexity for this problem?
easy
A. Use a greedy approach by repeatedly picking the smallest element from the matrix without extra data structures.
B. Flatten the matrix into a list, sort it, and return the kth element.
C. Apply dynamic programming to build a table of smallest elements up to k.
D. Use a min-heap to merge the sorted rows, extracting the smallest elements until the kth is found.

Solution

  1. Step 1: Understand problem constraints

    The matrix rows and columns are sorted, so each row is sorted and each column is sorted independently.
  2. Step 2: Identify the optimal approach

    Using a min-heap to merge sorted rows efficiently extracts the smallest elements in ascending order, achieving O(k log n) time, better than flattening and sorting.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Min-heap merges sorted lists optimally [OK]
Hint: Min-heap merges sorted rows efficiently [OK]
Common Mistakes:
  • Assuming flatten and sort is optimal
  • Confusing DP with this problem
  • Thinking greedy without data structures works
2. Examine the following buggy code snippet for finding the smallest divisor. Which line contains the subtle bug that can cause incorrect results on some inputs?
medium
A. Line with total += num // divisor
B. Line with if total > threshold:
C. Line with mid = (low + high) // 2
D. Line with low, high = 1, max(nums)

Solution

  1. Step 1: Identify the purpose of is_feasible

    It sums the ceiling division of each num by divisor to check if total ≤ threshold.
  2. Step 2: Spot the bug in division

    Using integer division (//) underestimates the sum because it truncates instead of rounding up.
  3. Step 3: Consequence of the bug

    Underestimating sum may cause the function to incorrectly return True, leading to wrong smallest divisor.
  4. Final Answer:

    Option A -> Option A
  5. Quick Check:

    Ceiling division needed, integer division breaks correctness -> [OK]
Hint: Ceiling division needed, integer division underestimates sum [OK]
Common Mistakes:
  • Using integer division instead of ceiling
  • Incorrect binary search boundaries
  • Not early exiting feasibility check
3. Consider the following buggy code for the Koko Eating Bananas problem. Which line contains the subtle bug that can cause incorrect results on some inputs?
from math import ceil

def can_finish(piles, speed, h):
    hours = 0
    for pile in piles:
        hours += pile // speed  # Line 6
        if hours > h:
            return false
    return true

def minEatingSpeed(piles, h):
    low, high = 1, max(piles)
    while low < high:
        mid = (low + high) // 2
        if can_finish(piles, mid, h):
            high = mid
        else:
            low = mid + 1
    return low
medium
A. Line 9: Returning true when hours <= h
B. Line 3: import statement
C. Line 6: Using floor division instead of ceiling division
D. Line 14: Updating low to mid + 1

Solution

  1. Step 1: Identify how hours are calculated

    Line 6 uses floor division (pile // speed), which underestimates hours needed because partial piles still require a full hour.
  2. Step 2: Understand impact on feasibility

    Underestimating hours causes can_finish to return true incorrectly, leading to wrong minimum speed.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Replacing floor division with ceiling fixes the bug [OK]
Hint: Hours must be ceil(pile / speed), not floor division [OK]
Common Mistakes:
  • Using floor division instead of ceiling
  • Misinterpreting feasibility condition
4. What is the time complexity of the optimal solution that uses binary search on the answer space combined with prefix sums and binary search for feasibility checks in the Split Array Largest Sum problem?
medium
A. O(n log(sum(nums))) since binary search is done only on sums without extra binary searches
B. O(n^m) due to exploring all splits recursively
C. O(n^2 log(sum(nums))) because feasibility check scans all subarrays linearly
D. O(n log n log(sum(nums))) because each binary search iteration uses binary search on prefix sums

Solution

  1. Step 1: Identify outer binary search on answer space

    Binary search on possible sums takes O(log(sum(nums))) iterations.
  2. Step 2: Analyze feasibility check using binary search on prefix sums

    Each feasibility check uses binary search (O(log n)) for each subarray, repeated up to n times -> O(n log n).
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Nested binary searches yield O(n log n log(sum(nums))) [OK]
Hint: Feasibility check uses binary search inside binary search [OK]
Common Mistakes:
  • Assuming feasibility check is O(n) ignoring binary search
  • Confusing n and m in complexity
  • Ignoring log factor from binary search on sums
5. Suppose the rotated sorted array may contain duplicate elements. Which modification to the pivot-finding algorithm is necessary to correctly find the pivot in O(log n) time in the worst case?
hard
A. Add a linear scan fallback when nums[mid] == nums[high] to reduce high by one.
B. Use a hash map to store visited indices to avoid infinite loops.
C. No modification needed; the existing pivot-finding algorithm works unchanged.
D. Switch to linear search for pivot since duplicates break binary search.

Solution

  1. Step 1: Understand duplicates impact

    Duplicates can cause nums[mid] == nums[high], making it unclear which half is sorted.
  2. Step 2: Modify pivot search

    When nums[mid] == nums[high], reduce high by one to shrink search space safely.
  3. Step 3: Complexity consideration

    This modification keeps worst-case complexity close to O(n) but often better than linear scan.
  4. Final Answer:

    Option A -> Option A
  5. Quick Check:

    Reducing high on equality handles duplicates correctly [OK]
Hint: Handle nums[mid]==nums[high] by decrementing high [OK]
Common Mistakes:
  • Assuming no duplicates
  • Switching to linear search unnecessarily
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard