Top Array Interview Questions with Solutions (C++, Java, JS, Python)
This page collects the array interview questions that show up again and again at startups and FAANG alike. Each one gives the problem, the approach, the complexity, and a complete solution you can read in C++, Java, JavaScript, or Python with the language switcher. If arrays are still fuzzy, review the arrays introduction first, then practice on the array exercises.
How to use this page: Read the question, pause and try it yourself, then check the approach and code. The recurring tricks here — hash maps, prefix products, two pointers, and Kadane’s running sum — cover a huge fraction of real interviews.
1. Two Sum
Question. Given an array nums and a target, return the indices of the two numbers that add up to target. Exactly one solution exists.
Approach. The brute force checks every pair in O(n²). Instead, walk once with a hash map of value → index; for each x, check whether target - x was already seen.
Complexity. O(n) time, O(n) space.
#include <vector>
#include <unordered_map>
std::vector<int> twoSum(const std::vector<int>& nums, int target) {
std::unordered_map<int, int> seen;
for (int i = 0; i < (int)nums.size(); i++) {
int need = target - nums[i];
if (seen.count(need)) return {seen[need], i};
seen[nums[i]] = i;
}
return {};
}
import java.util.HashMap;
import java.util.Map;
int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> seen = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int need = target - nums[i];
if (seen.containsKey(need)) return new int[]{seen.get(need), i};
seen.put(nums[i], i);
}
return new int[]{};
}
function twoSum(nums, target) {
const seen = new Map();
for (let i = 0; i < nums.length; i++) {
const need = target - nums[i];
if (seen.has(need)) return [seen.get(need), i];
seen.set(nums[i], i);
}
return [];
}
def two_sum(nums, target):
seen = {}
for i, x in enumerate(nums):
need = target - x
if need in seen:
return [seen[need], i]
seen[x] = i
return []
2. Best Time to Buy and Sell Stock
Question. Given daily prices, find the maximum profit from one buy followed by one later sell. If no profit is possible, return 0.
Approach. Track the lowest price so far as you scan left to right; at each day, the best sale today is price - minSoFar. Keep the maximum.
Complexity. O(n) time, O(1) space.
#include <vector>
#include <algorithm>
#include <climits>
int maxProfit(const std::vector<int>& prices) {
int minPrice = INT_MAX, best = 0;
for (int p : prices) {
minPrice = std::min(minPrice, p);
best = std::max(best, p - minPrice);
}
return best;
}
int maxProfit(int[] prices) {
int minPrice = Integer.MAX_VALUE, best = 0;
for (int p : prices) {
minPrice = Math.min(minPrice, p);
best = Math.max(best, p - minPrice);
}
return best;
}
function maxProfit(prices) {
let minPrice = Infinity, best = 0;
for (const p of prices) {
minPrice = Math.min(minPrice, p);
best = Math.max(best, p - minPrice);
}
return best;
}
def max_profit(prices):
min_price, best = float("inf"), 0
for p in prices:
min_price = min(min_price, p)
best = max(best, p - min_price)
return best
3. Contains Duplicate
Question. Return true if any value appears at least twice in the array, otherwise false.
Approach. Insert values into a hash set as you go; if a value is already present, you found a duplicate. (Sorting first and checking neighbours also works in O(n log n).)
Complexity. O(n) time, O(n) space.
#include <vector>
#include <unordered_set>
bool containsDuplicate(const std::vector<int>& nums) {
std::unordered_set<int> seen;
for (int x : nums) {
if (seen.count(x)) return true;
seen.insert(x);
}
return false;
}
import java.util.HashSet;
import java.util.Set;
boolean containsDuplicate(int[] nums) {
Set<Integer> seen = new HashSet<>();
for (int x : nums) {
if (!seen.add(x)) return true; // add returns false if already present
}
return false;
}
function containsDuplicate(nums) {
const seen = new Set();
for (const x of nums) {
if (seen.has(x)) return true;
seen.add(x);
}
return false;
}
def contains_duplicate(nums):
seen = set()
for x in nums:
if x in seen:
return True
seen.add(x)
return False
4. Product of Array Except Self
Question. Return an array where output[i] is the product of every element except nums[i]. Do it without division.
Approach. Two passes. First store the running prefix product to the left of each index; then multiply in the running suffix product from the right. The output array doubles as scratch space.
Complexity. O(n) time, O(1) extra space (excluding the output).
#include <vector>
std::vector<int> productExceptSelf(const std::vector<int>& a) {
int n = a.size();
std::vector<int> res(n, 1);
int prefix = 1;
for (int i = 0; i < n; i++) { res[i] = prefix; prefix *= a[i]; }
int suffix = 1;
for (int i = n - 1; i >= 0; i--) { res[i] *= suffix; suffix *= a[i]; }
return res;
}
int[] productExceptSelf(int[] a) {
int n = a.length;
int[] res = new int[n];
int prefix = 1;
for (int i = 0; i < n; i++) { res[i] = prefix; prefix *= a[i]; }
int suffix = 1;
for (int i = n - 1; i >= 0; i--) { res[i] *= suffix; suffix *= a[i]; }
return res;
}
function productExceptSelf(a) {
const n = a.length;
const res = new Array(n).fill(1);
let prefix = 1;
for (let i = 0; i < n; i++) { res[i] = prefix; prefix *= a[i]; }
let suffix = 1;
for (let i = n - 1; i >= 0; i--) { res[i] *= suffix; suffix *= a[i]; }
return res;
}
def product_except_self(a):
n = len(a)
res = [1] * n
prefix = 1
for i in range(n):
res[i] = prefix
prefix *= a[i]
suffix = 1
for i in range(n - 1, -1, -1):
res[i] *= suffix
suffix *= a[i]
return res
5. Maximum Subarray (Kadane’s Algorithm)
Question. Find the largest sum of any contiguous subarray.
Approach. At each index, decide whether to extend the current subarray or start fresh at this element. A negative running sum can only hurt what follows, so discard it. Track the best sum seen.
Complexity. O(n) time, O(1) space.
#include <vector>
#include <algorithm>
int maxSubArray(const std::vector<int>& a) {
int best = a[0], cur = a[0];
for (int i = 1; i < (int)a.size(); i++) {
cur = std::max(a[i], cur + a[i]);
best = std::max(best, cur);
}
return best;
}
int maxSubArray(int[] a) {
int best = a[0], cur = a[0];
for (int i = 1; i < a.length; i++) {
cur = Math.max(a[i], cur + a[i]);
best = Math.max(best, cur);
}
return best;
}
function maxSubArray(a) {
let best = a[0], cur = a[0];
for (let i = 1; i < a.length; i++) {
cur = Math.max(a[i], cur + a[i]);
best = Math.max(best, cur);
}
return best;
}
def max_sub_array(a):
best = cur = a[0]
for x in a[1:]:
cur = max(x, cur + x)
best = max(best, cur)
return best
6. Merge Intervals
Question. Given a list of intervals [start, end], merge all overlapping intervals.
Approach. Sort by start. Walk the sorted list; if the current interval starts at or before the end of the last merged interval, extend that interval’s end, otherwise append it as new.
Complexity. O(n log n) time (the sort dominates), O(n) space for the output.
#include <vector>
#include <algorithm>
std::vector<std::vector<int>> merge(std::vector<std::vector<int>>& intervals) {
std::sort(intervals.begin(), intervals.end());
std::vector<std::vector<int>> res;
for (auto& iv : intervals) {
if (!res.empty() && iv[0] <= res.back()[1])
res.back()[1] = std::max(res.back()[1], iv[1]);
else
res.push_back(iv);
}
return res;
}
import java.util.*;
int[][] merge(int[][] intervals) {
Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));
List<int[]> res = new ArrayList<>();
for (int[] iv : intervals) {
int last = res.size() - 1;
if (!res.isEmpty() && iv[0] <= res.get(last)[1])
res.get(last)[1] = Math.max(res.get(last)[1], iv[1]);
else
res.add(iv);
}
return res.toArray(new int[0][]);
}
function merge(intervals) {
intervals.sort((a, b) => a[0] - b[0]);
const res = [];
for (const iv of intervals) {
const last = res[res.length - 1];
if (last && iv[0] <= last[1]) last[1] = Math.max(last[1], iv[1]);
else res.push(iv.slice());
}
return res;
}
def merge(intervals):
intervals.sort(key=lambda iv: iv[0])
res = []
for iv in intervals:
if res and iv[0] <= res[-1][1]:
res[-1][1] = max(res[-1][1], iv[1])
else:
res.append(iv[:])
return res
7. Rotate Array
Question. Rotate the array to the right by k steps, in place.
Approach. The clean O(1)-space trick is three reversals: reverse the whole array, then reverse the first k elements, then reverse the rest. Take k % n first so large k wraps correctly.
Complexity. O(n) time, O(1) extra space.
#include <vector>
#include <algorithm>
void rotate(std::vector<int>& a, int k) {
int n = a.size();
if (n == 0) return;
k %= n;
std::reverse(a.begin(), a.end());
std::reverse(a.begin(), a.begin() + k);
std::reverse(a.begin() + k, a.end());
}
void rotate(int[] a, int k) {
int n = a.length;
if (n == 0) return;
k %= n;
reverse(a, 0, n - 1);
reverse(a, 0, k - 1);
reverse(a, k, n - 1);
}
void reverse(int[] a, int i, int j) {
while (i < j) { int t = a[i]; a[i] = a[j]; a[j] = t; i++; j--; }
}
function rotate(a, k) {
const n = a.length;
if (n === 0) return;
k %= n;
reverse(a, 0, n - 1);
reverse(a, 0, k - 1);
reverse(a, k, n - 1);
}
function reverse(a, i, j) {
while (i < j) { [a[i], a[j]] = [a[j], a[i]]; i++; j--; }
}
def rotate(a, k):
n = len(a)
if n == 0:
return
k %= n
a.reverse()
a[:k] = reversed(a[:k])
a[k:] = reversed(a[k:])
Pitfall: Forgetting
k %= noverflows array bounds whenk > n. And in the three-reversal trick, reversing the whole array first is what makes the two sub-reversals land in the right place.
Keep practicing
These seven cover the dominant array patterns: hashing for lookups, prefix/suffix accumulation, running state (Kadane’s), sort-then-sweep, and in-place pointer tricks. Drill more on the array exercises, then move on to string interview questions.