Kazi Rahamatullah
Kazi Rahamatullah
AboutProjectsBlogContact
UsesBooks
ResumeView CV
Kazi Rahamatullah

© Copyright 2026 Kazi Rahamatullah

AboutProjectsBlogBooksUses
Twitter/XGitHubProduct HuntCodeSandbox
Back to Blog
DSAArraysInterviewAlgorithms

50 Array Coding Problems for Interviews — Solutions Explained

50 essential array interview problems from easy to hard — step-by-step approach, JavaScript solution, and function calls with output comments.

Jul 4, 202641 min read

Introduction

Array problems dominate coding interviews — from two-pointer tricks to Kadane's algorithm and sliding windows. This post covers 50 curated problems with:

  1. Step-by-step approach
  2. Full JavaScript implementation
  3. Function calls with side output comments

Prerequisites: DSA Arrays fundamentals · Big O notation

Quick index

#ProblemLevelTime
1Second Largest ElementEasyO(n)
2Third Largest ElementEasyO(n)
3Reverse an ArrayEasyO(n)
4Reverse Array in GroupsEasyO(n)
5Rotate ArrayEasyO(n)
6Three Largest Distinct ElementsEasyO(n)
7Max Consecutive OnesEasyO(n)
8Move All Zeroes To EndEasyO(n)
9Wave ArrayEasyO(n log n)
10Plus OneEasyO(n)
11Stock Buy and Sell — One TransactionEasyO(n)
12Stock Buy and Sell — Multiple TransactionsEasyO(n)
13Remove Duplicates from Sorted ArrayEasyO(n)
14Alternate Positive and NegativeEasyO(n)
15Array LeadersEasyO(n)
16Missing and Repeating in ArrayEasyO(n)
17Missing Ranges of NumbersEasyO(n)
18Sum of All SubarraysEasyO(n)
19Next PermutationMediumO(n)
20Majority ElementMediumO(n)
21Majority Element IIMediumO(n)
22Minimize Heights IIMediumO(n log n)
23Maximum Subarray Sum (Kadane)MediumO(n)
24Maximum Product SubarrayMediumO(n)
25Product of Array Except SelfMediumO(n)
26Subarrays with Product Less Than KMediumO(n)
27Split Into Three Equal Sum SegmentsMediumO(n)
28Max Consecutive 1s After Flipping K ZeroesMediumO(n)
29Last Moment Before Ants Fall Off PlankMediumO(n)
30Find 0 with Farthest 1s in Binary ArrayMediumO(n)
31Merge Two Sorted Interval ListsMediumO(n + m)
32Rearrange Array Elements by SignMediumO(n)
33Meeting Scheduler for Two PersonsMediumO(n log n)
34Longest Mountain SubarrayMediumO(n)
35Transform and Sort ArrayMediumO(n log n)
36Minimum Swaps To Group All OnesMediumO(n)
37Minimum Moves To Equalize ArrayMediumO(n)
38Minimum Indices To Equal Even-Odd SumsMediumO(n)
39Trapping Rain WaterHardO(n)
40Maximum Circular Subarray SumHardO(n)
41Smallest Missing Positive NumberHardO(n)
42Jump GameHardO(n)
43Closest Subsequence SumHardO(n · 2^(n/2))
44Smallest Non-Representable SumHardO(n log n)
45Smallest Range Covering K ListsHardO(n log k)
46Count Subarrays with K DistinctHardO(n)
47Next Smallest PalindromeHardO(n)
48Maximum Sum Among All RotationsHardO(n)
49Two SumEasyO(n)
50Container With Most WaterMediumO(n)

Easy (1–18)

1. Second Largest Element

Difficulty: Easy · Time: O(n) · Space: O(1)

Find the second largest element in an unsorted array. Return -1 if it does not exist.

Approach (step by step):

  1. Track first and second while scanning once.
  2. When x beats first, shift old first to second; otherwise update second if x is between them.
  3. Skip duplicates implicitly by only updating when strictly greater.
js
function secondLargest(arr) {
  let first = -Infinity,
    second = -Infinity
  for (const x of arr) {
    if (x > first) {
      second = first
      first = x
    } else if (x > second && x < first) {
      second = x
    }
  }
  return second === -Infinity ? -1 : second
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
secondLargest([12, 35, 1, 10, 34, 1]) // → 34
secondLargest([10, 10, 10]) // → -1
secondLargest([5, 5, 4]) // → 4

Back to index


2. Third Largest Element

Difficulty: Easy · Time: O(n) · Space: O(1)

Return the third distinct largest element, or -1 if fewer than three distinct values exist.

Approach (step by step):

  1. Maintain three variables: first, second, third.
  2. On each value, cascade updates when a new maximum appears.
  3. Return third only if it was set.
js
function thirdLargest(arr) {
  let a = -Infinity,
    b = -Infinity,
    c = -Infinity
  for (const x of arr) {
    if (x > a) {
      c = b
      b = a
      a = x
    } else if (x > b && x < a) {
      c = b
      b = x
    } else if (x > c && x < b) {
      c = x
    }
  }
  return c === -Infinity ? -1 : c
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
thirdLargest([1, 2, 3, 4, 5]) // → 3
thirdLargest([5, 5, 5]) // → -1

Back to index


3. Reverse an Array

Difficulty: Easy · Time: O(n) · Space: O(1)

Reverse the array in-place using two pointers.

Approach (step by step):

  1. Place left at 0 and right at n − 1.
  2. Swap and move inward until pointers meet.
js
function reverseArray(arr) {
  let l = 0,
    r = arr.length - 1
  while (l < r) {
    ;[arr[l], arr[r]] = [arr[r], arr[l]]
    l++
    r--
  }
  return arr
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
reverseArray([1, 2, 3, 4]) // → [4, 3, 2, 1]
reverseArray([10]) // → [10]

Back to index


4. Reverse Array in Groups

Difficulty: Easy · Time: O(n) · Space: O(1)

Reverse every subarray of size k. If the last group has fewer than k elements, reverse all remaining.

Approach (step by step):

  1. Step by i in increments of k.
  2. Reverse the slice from i to min(i + k - 1, n - 1).
js
function reverseInGroups(arr, k) {
  const n = arr.length
  for (let i = 0; i < n; i += k) {
    let l = i,
      r = Math.min(i + k - 1, n - 1)
    while (l < r) {
      ;[arr[l], arr[r]] = [arr[r], arr[l]]
      l++
      r--
    }
  }
  return arr
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
reverseInGroups([1, 2, 3, 4, 5, 6, 7, 8], 3) // → [3, 2, 1, 6, 5, 4, 8, 7]
reverseInGroups([1, 2, 3, 4, 5], 2) // → [2, 1, 4, 3, 5]

Back to index


5. Rotate Array

Difficulty: Easy · Time: O(n) · Space: O(1)

Rotate array to the right by k steps in-place.

Approach (step by step):

  1. Normalize k %= n.
  2. Reverse whole array, then reverse first k and last n-k parts.
js
function rotateArray(arr, k) {
  const n = arr.length
  if (!n) return arr
  k %= n
  const rev = (l, r) => {
    while (l < r) {
      ;[arr[l], arr[r]] = [arr[r], arr[l]]
      l++
      r--
    }
  }
  rev(0, n - 1)
  rev(0, k - 1)
  rev(k, n - 1)
  return arr
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
rotateArray([1, 2, 3, 4, 5], 2) // → [4, 5, 1, 2, 3]
rotateArray([1, 2], 3) // → [2, 1]

Back to index


6. Three Largest Distinct Elements

Difficulty: Easy · Time: O(n) · Space: O(1)

Return the three largest distinct elements in descending order.

Approach (step by step):

  1. Use a Set to dedupe, sort descending, take first three.
js
function threeLargestDistinct(arr) {
  return [...new Set(arr)].sort((a, b) => b - a).slice(0, 3)
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
threeLargestDistinct([1, 2, 4, 4, 5, 5, 3]) // → [5, 4, 3]
threeLargestDistinct([10, 10]) // → [10]

Back to index


7. Max Consecutive Ones

Difficulty: Easy · Time: O(n) · Space: O(1)

Find the maximum number of consecutive 1s in a binary array.

Approach (step by step):

  1. Track current streak and global max; reset streak on 0.
js
function maxConsecutiveOnes(arr) {
  let cur = 0,
    best = 0
  for (const x of arr) {
    cur = x === 1 ? cur + 1 : 0
    best = Math.max(best, cur)
  }
  return best
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
maxConsecutiveOnes([1, 1, 0, 1, 1, 1]) // → 3
maxConsecutiveOnes([1, 0, 1, 1, 0, 1]) // → 2

Back to index


8. Move All Zeroes To End

Difficulty: Easy · Time: O(n) · Space: O(1)

Move all zeroes to the end while maintaining relative order of non-zero elements.

Approach (step by step):

  1. Two-pointer: write non-zero values at write index, fill rest with 0.
js
function moveZeroes(arr) {
  let w = 0
  for (const x of arr) if (x !== 0) arr[w++] = x
  while (w < arr.length) arr[w++] = 0
  return arr
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
moveZeroes([0, 1, 0, 3, 12]) // → [1, 3, 12, 0, 0]
moveZeroes([0, 0, 1]) // → [1, 0, 0]

Back to index


9. Wave Array

Difficulty: Easy · Time: O(n log n) · Space: O(1)

Arrange array so arr[0] ≥ arr[1] ≤ arr[2] ≥ arr[3]... (wave form).

Approach (step by step):

  1. Sort ascending, then swap pairs (1,2), (3,4), ....
js
function waveArray(arr) {
  arr.sort((a, b) => a - b)
  for (let i = 1; i < arr.length - 1; i += 2) {
    ;[arr[i], arr[i + 1]] = [arr[i + 1], arr[i]]
  }
  return arr
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
waveArray([1, 2, 3, 4, 5, 6]) // → [1, 3, 2, 5, 4, 6]
waveArray([10, 90, 49, 2]) // → [2, 49, 10, 90]

Back to index


10. Plus One

Difficulty: Easy · Time: O(n) · Space: O(1)

Add 1 to a non-negative integer represented as digit array (MSB first).

Approach (step by step):

  1. Traverse from end, propagate carry, prepend 1 if overflow.
js
function plusOne(digits) {
  for (let i = digits.length - 1; i >= 0; i--) {
    if (digits[i] < 9) {
      digits[i]++
      return digits
    }
    digits[i] = 0
  }
  return [1, ...digits]
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
plusOne([1, 2, 3]) // → [1, 2, 4]
plusOne([9, 9, 9]) // → [1, 0, 0, 0]

Back to index


11. Stock Buy and Sell — One Transaction

Difficulty: Easy · Time: O(n) · Space: O(1)

Max profit from at most one buy and one sell.

Approach (step by step):

  1. Track minimum price so far; update max profit at each day.
js
function maxProfitOne(prices) {
  let minP = Infinity,
    best = 0
  for (const p of prices) {
    minP = Math.min(minP, p)
    best = Math.max(best, p - minP)
  }
  return best
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
maxProfitOne([7, 1, 5, 3, 6, 4]) // → 5
maxProfitOne([7, 6, 4, 3, 1]) // → 0

Back to index


12. Stock Buy and Sell — Multiple Transactions

Difficulty: Easy · Time: O(n) · Space: O(1)

Max profit with unlimited transactions (no overlapping holds).

Approach (step by step):

  1. Sum every upward day: if prices[i] > prices[i-1], add difference.
js
function maxProfitMany(prices) {
  let profit = 0
  for (let i = 1; i < prices.length; i++) {
    if (prices[i] > prices[i - 1]) profit += prices[i] - prices[i - 1]
  }
  return profit
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
maxProfitMany([7, 1, 5, 3, 6, 4]) // → 7
maxProfitMany([1, 2, 3, 4, 5]) // → 4

Back to index


13. Remove Duplicates from Sorted Array

Difficulty: Easy · Time: O(n) · Space: O(1)

Remove duplicates in-place; return count of unique elements.

Approach (step by step):

  1. Slow pointer marks last unique; fast scans and copies new values.
js
function removeDuplicates(arr) {
  if (!arr.length) return 0
  let w = 1
  for (let i = 1; i < arr.length; i++) {
    if (arr[i] !== arr[w - 1]) arr[w++] = arr[i]
  }
  return w
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
removeDuplicates([1, 1, 2, 2, 3]) // → 3  (array starts [1,2,3])
removeDuplicates([1, 2, 3]) // → 3

Back to index


14. Alternate Positive and Negative

Difficulty: Easy · Time: O(n) · Space: O(n)

Rearrange so positives and negatives alternate. Order among same sign may change.

Approach (step by step):

  1. Split into pos/neg arrays, merge alternating starting with sign of first non-zero.
js
function alternateSign(arr) {
  const pos = arr.filter((x) => x > 0)
  const neg = arr.filter((x) => x < 0)
  const out = []
  let i = 0,
    j = 0
  while (i < pos.length || j < neg.length) {
    if (i < pos.length) out.push(pos[i++])
    if (j < neg.length) out.push(neg[j++])
  }
  return out
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
alternateSign([1, -2, 3, -4, 5]) // → [1, -2, 3, -4, 5]
alternateSign([-1, -2, 3, 4]) // → [3, -1, 4, -2]

Back to index


15. Array Leaders

Difficulty: Easy · Time: O(n) · Space: O(1)

An element is a leader if it is greater than all elements to its right.

Approach (step by step):

  1. Scan right-to-left; track running max from the right.
js
function arrayLeaders(arr) {
  const leaders = []
  let maxR = -Infinity
  for (let i = arr.length - 1; i >= 0; i--) {
    if (arr[i] >= maxR) {
      leaders.push(arr[i])
      maxR = arr[i]
    }
  }
  return leaders.reverse()
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
arrayLeaders([16, 17, 4, 3, 5, 2]) // → [17, 5, 2]
arrayLeaders([10, 4, 3, 2]) // → [10, 4, 3, 2]

Back to index


16. Missing and Repeating in Array

Difficulty: Easy · Time: O(n) · Space: O(1)

Array of 1..n has one missing and one repeating number. Find both.

Approach (step by step):

  1. Use math: sum and sum of squares, or XOR/index marking.
js
function missingAndRepeating(arr) {
  const n = arr.length
  let sum = 0,
    sq = 0
  for (const x of arr) {
    sum += x
    sq += x * x
  }
  const tSum = (n * (n + 1)) / 2
  const tSq = (n * (n + 1) * (2 * n + 1)) / 6
  const d = sum - tSum
  const dSq = sq - tSq
  const repeating = (dSq / d + d) / 2
  const missing = repeating - d
  return { missing, repeating }
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
missingAndRepeating([4, 3, 6, 2, 1, 1]) // → { missing: 5, repeating: 1 }

Back to index


17. Missing Ranges of Numbers

Difficulty: Easy · Time: O(n) · Space: O(1)

Given sorted unique array within [low, high], return missing ranges as strings.

Approach (step by step):

  1. Walk array; between consecutive values emit missing intervals.
js
function missingRanges(arr, low, high) {
  const out = []
  let prev = low - 1
  const nums = [low - 1, ...arr, high + 1]
  for (const cur of nums.slice(1)) {
    if (cur - prev === 2) out.push(String(prev + 1))
    else if (cur - prev > 2) out.push(`${prev + 1}->${cur - 1}`)
    prev = cur
  }
  return out
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
missingRanges([0, 1, 3, 50, 75], 0, 99) // → ["2", "4->49", "51->74", "76->99"]
missingRanges([], 1, 1) // → ["1"]

Back to index


18. Sum of All Subarrays

Difficulty: Easy · Time: O(n) · Space: O(1)

Return sum of all subarray sums efficiently.

Approach (step by step):

  1. Each arr[i] appears in (i+1) * (n-i) subarrays; multiply and sum.
js
function subarraySumTotal(arr) {
  let total = 0
  const n = arr.length
  for (let i = 0; i < n; i++) total += arr[i] * (i + 1) * (n - i)
  return total
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
subarraySumTotal([1, 2, 3]) // → 20
subarraySumTotal([1, 3]) // → 8

Back to index


Medium (19–38)

19. Next Permutation

Difficulty: Medium · Time: O(n) · Space: O(1)

Rearrange to the next lexicographically greater permutation in-place.

Approach (step by step):

  1. Find rightmost ascent i where arr[i] < arr[i+1].
  2. Swap arr[i] with smallest larger element on the right.
  3. Reverse suffix after i.
js
function nextPermutation(arr) {
  let i = arr.length - 2
  while (i >= 0 && arr[i] >= arr[i + 1]) i--
  if (i >= 0) {
    let j = arr.length - 1
    while (arr[j] <= arr[i]) j--
    ;[arr[i], arr[j]] = [arr[j], arr[i]]
  }
  let l = i + 1,
    r = arr.length - 1
  while (l < r) {
    ;[arr[l], arr[r]] = [arr[r], arr[l]]
    l++
    r--
  }
  return arr
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
nextPermutation([1, 2, 3]) // → [1, 3, 2]
nextPermutation([3, 2, 1]) // → [1, 2, 3]

Back to index


20. Majority Element

Difficulty: Medium · Time: O(n) · Space: O(1)

Find element appearing more than n/2 times (assume it always exists).

Approach (step by step):

  1. Boyer–Moore: cancel different pairs; survivor is majority.
js
function majorityElement(arr) {
  let cand = arr[0],
    count = 1
  for (let i = 1; i < arr.length; i++) {
    if (arr[i] === cand) count++
    else if (--count === 0) {
      cand = arr[i]
      count = 1
    }
  }
  return cand
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
majorityElement([3, 3, 4, 2, 4, 4, 2, 4, 4]) // → 4
majorityElement([2, 2, 1, 1, 1, 2, 2]) // → 2

Back to index


21. Majority Element II

Difficulty: Medium · Time: O(n) · Space: O(1)

Find all elements appearing more than n/3 times.

Approach (step by step):

  1. Boyer–Moore extended with two candidates, then verify counts.
js
function majorityElementII(arr) {
  let c1 = null,
    c2 = null,
    cnt1 = 0,
    cnt2 = 0
  for (const x of arr) {
    if (x === c1) cnt1++
    else if (x === c2) cnt2++
    else if (cnt1 === 0) {
      c1 = x
      cnt1 = 1
    } else if (cnt2 === 0) {
      c2 = x
      cnt2 = 1
    } else {
      cnt1--
      cnt2--
    }
  }
  const verify = (c) => (arr.filter((x) => x === c).length > arr.length / 3 ? c : null)
  return [verify(c1), verify(c2)].filter((x) => x !== null)
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
majorityElementII([3, 2, 3]) // → [3]
majorityElementII([1, 1, 1, 3, 3, 2, 2, 2]) // → [1, 2]

Back to index


22. Minimize Heights II

Difficulty: Medium · Time: O(n log n) · Space: O(1)

Minimize max - min after adding/subtracting k to each element exactly once.

Approach (step by step):

  1. Sort; try making first i elements smaller and rest larger; track min diff.
js
function minimizeHeights(arr, k) {
  arr.sort((a, b) => a - b)
  const n = arr.length
  let best = arr[n - 1] - arr[0]
  for (let i = 0; i < n - 1; i++) {
    const low = Math.min(arr[0] + k, arr[i + 1] - k)
    const high = Math.max(arr[i] + k, arr[n - 1] - k)
    best = Math.min(best, high - low)
  }
  return best
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
minimizeHeights([1, 5, 8, 10], 2) // → 5
minimizeHeights([3, 9, 12, 16, 20], 3) // → 11

Back to index


23. Maximum Subarray Sum (Kadane)

Difficulty: Medium · Time: O(n) · Space: O(1)

Find contiguous subarray with largest sum.

Approach (step by step):

  1. Extend running sum or restart at current element; track global max.
js
function maxSubarraySum(arr) {
  let cur = arr[0],
    best = arr[0]
  for (let i = 1; i < arr.length; i++) {
    cur = Math.max(arr[i], cur + arr[i])
    best = Math.max(best, cur)
  }
  return best
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
maxSubarraySum([-2, 1, -3, 4, -1, 2, 1, -5, 4]) // → 6
maxSubarraySum([5, 4, -1, 7, 8]) // → 23

Back to index


24. Maximum Product Subarray

Difficulty: Medium · Time: O(n) · Space: O(1)

Find contiguous subarray with largest product.

Approach (step by step):

  1. Track both max and min ending here (negatives flip).
js
function maxProductSubarray(arr) {
  let best = arr[0],
    maxE = arr[0],
    minE = arr[0]
  for (let i = 1; i < arr.length; i++) {
    const x = arr[i]
    const candidates = [x, maxE * x, minE * x]
    maxE = Math.max(...candidates)
    minE = Math.min(...candidates)
    best = Math.max(best, maxE)
  }
  return best
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
maxProductSubarray([2, 3, -2, 4]) // → 6
maxProductSubarray([-2, 0, -1]) // → 0

Back to index


25. Product of Array Except Self

Difficulty: Medium · Time: O(n) · Space: O(1)

Return array where output[i] is product of all elements except arr[i] without division.

Approach (step by step):

  1. Prefix products left-to-right, then multiply suffix running product right-to-left.
js
function productExceptSelf(arr) {
  const n = arr.length
  const out = Array(n).fill(1)
  let prefix = 1
  for (let i = 0; i < n; i++) {
    out[i] = prefix
    prefix *= arr[i]
  }
  let suffix = 1
  for (let i = n - 1; i >= 0; i--) {
    out[i] *= suffix
    suffix *= arr[i]
  }
  return out
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
productExceptSelf([1, 2, 3, 4]) // → [24, 12, 8, 6]
productExceptSelf([2, 3, 4, 5]) // → [60, 40, 30, 24]

Back to index


26. Subarrays with Product Less Than K

Difficulty: Medium · Time: O(n) · Space: O(1)

Count contiguous subarrays whose product is strictly less than k.

Approach (step by step):

  1. Sliding window: expand right, shrink left while product ≥ k.
js
function subarrayProductLessK(arr, k) {
  if (k <= 1) return 0
  let prod = 1,
    left = 0,
    count = 0
  for (let right = 0; right < arr.length; right++) {
    prod *= arr[right]
    while (prod >= k) prod /= arr[left++]
    count += right - left + 1
  }
  return count
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
subarrayProductLessK([10, 5, 2, 6], 100) // → 8
subarrayProductLessK([1, 2, 3], 0) // → 0

Back to index


27. Split Into Three Equal Sum Segments

Difficulty: Medium · Time: O(n) · Space: O(1)

Check if array can be split into three non-empty parts with equal sum.

Approach (step by step):

  1. Compute total sum; find prefix cut at sum/3 and second cut at 2*sum/3.
js
function canSplitThreeEqual(arr) {
  const total = arr.reduce((a, b) => a + b, 0)
  if (total % 3 !== 0) return false
  const part = total / 3
  let sum = 0,
    cuts = 0
  for (let i = 0; i < arr.length - 1; i++) {
    sum += arr[i]
    if (sum === part) {
      cuts++
      if (cuts === 2) return true
    }
  }
  return false
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
canSplitThreeEqual([0, 2, 1, -6, 6, -1, 1, 0, 1]) // → true
canSplitThreeEqual([1, 1, 1]) // → false

Back to index


28. Max Consecutive 1s After Flipping K Zeroes

Difficulty: Medium · Time: O(n) · Space: O(1)

Longest subarray of 1s if you can flip at most k zeroes.

Approach (step by step):

  1. Sliding window maintains count of zeroes ≤ k.
js
function maxConsecutiveOnesFlip(arr, k) {
  let left = 0,
    zeros = 0,
    best = 0
  for (let right = 0; right < arr.length; right++) {
    if (arr[right] === 0) zeros++
    while (zeros > k) if (arr[left++] === 0) zeros--
    best = Math.max(best, right - left + 1)
  }
  return best
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
maxConsecutiveOnesFlip([1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0], 2) // → 6
maxConsecutiveOnesFlip([0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1], 3) // → 10

Back to index


29. Last Moment Before Ants Fall Off Plank

Difficulty: Medium · Time: O(n) · Space: O(1)

Ants on a line move left/right at speed 1. Return time when last ant falls.

Approach (step by step):

  1. Max time is max of left-going distance and right-going distance.
js
function lastMomentAnts(n, positions, directions) {
  let left = 0,
    right = 0
  for (let i = 0; i < positions.length; i++) {
    if (directions[i] === 0) left = Math.max(left, positions[i])
    else right = Math.max(right, n - positions[i])
  }
  return Math.max(left, right)
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
lastMomentAnts(4, [3, 2], [0, 1]) // → 2
lastMomentAnts(7, [0, 4, 7], [0, 0, 1]) // → 7

Back to index


30. Find 0 with Farthest 1s in Binary Array

Difficulty: Medium · Time: O(n) · Space: O(1)

Flip one 0 to maximize distance to nearest 1; return index to flip.

Approach (step by step):

  1. Scan groups of consecutive zeroes between ones; handle edges separately.
js
function findBestZeroToFlip(arr) {
  let best = -1,
    bestLen = -1
  let prevOne = -1
  for (let i = 0; i <= arr.length; i++) {
    if (i === arr.length || arr[i] === 1) {
      const len = prevOne === -1 ? i : i - prevOne - 1
      const dist = prevOne === -1 || i === arr.length ? len : Math.ceil(len / 2)
      if (dist > bestLen) {
        bestLen = dist
        best = prevOne === -1 ? 0 : prevOne + Math.floor(len / 2) + 1
      }
      if (i < arr.length) prevOne = i
    }
  }
  return best
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
findBestZeroToFlip([1, 0, 0, 0, 1]) // → 2
findBestZeroToFlip([0, 0, 0, 1]) // → 0

Back to index


31. Merge Two Sorted Interval Lists

Difficulty: Medium · Time: O(n + m) · Space: O(1)

Merge two sorted interval arrays into one sorted non-overlapping list.

Approach (step by step):

  1. Standard merge by start time; combine overlapping intervals.
js
function mergeIntervals(a, b) {
  const all = [...a, ...b].sort((x, y) => x[0] - y[0])
  const out = []
  for (const iv of all) {
    if (!out.length || out[out.length - 1][1] < iv[0]) out.push([...iv])
    else out[out.length - 1][1] = Math.max(out[out.length - 1][1], iv[1])
  }
  return out
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
mergeIntervals(
  [
    [1, 3],
    [5, 7],
  ],
  [
    [2, 4],
    [6, 8],
  ],
) // → [[1,4],[5,8]]
mergeIntervals([[1, 2]], [[3, 4]]) // → [[1,2],[3,4]]

Back to index


32. Rearrange Array Elements by Sign

Difficulty: Medium · Time: O(n) · Space: O(n)

Equal counts of positive and negative; alternate starting with positive.

Approach (step by step):

  1. Collect positives and negatives; interleave into result.
js
function rearrangeBySign(arr) {
  const pos = [],
    neg = []
  for (const x of arr) (x >= 0 ? pos : neg).push(x)
  const out = []
  for (let i = 0; i < pos.length; i++) {
    out.push(pos[i], neg[i])
  }
  return out
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
rearrangeBySign([3, 1, -2, -5, 2, -4]) // → [3, -2, 1, -5, 2, -4]

Back to index


33. Meeting Scheduler for Two Persons

Difficulty: Medium · Time: O(n log n) · Space: O(1)

Find earliest slot of duration dur where both people are free within [start, end].

Approach (step by step):

  1. Merge each person’s busy slots, two-pointer scan gaps.
js
function meetingScheduler(slotsA, slotsB, dur) {
  const merge = (s) => s.sort((a, b) => a[0] - b[0])
  const busy = [...merge(slotsA), ...merge(slotsB)].sort((a, b) => a[0] - b[0])
  let prevEnd = busy[0]?.[0] ?? 0
  for (const [s, e] of busy) {
    if (s - prevEnd >= dur) return [prevEnd, prevEnd + dur]
    prevEnd = Math.max(prevEnd, e)
  }
  return []
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
meetingScheduler(
  [
    [10, 50],
    [60, 120],
  ],
  [
    [0, 15],
    [60, 70],
  ],
  8,
) // → [15, 23]

Back to index


34. Longest Mountain Subarray

Difficulty: Medium · Time: O(n) · Space: O(1)

Longest subarray that increases then decreases (length ≥ 3).

Approach (step by step):

  1. For each peak, expand left while ascending and right while descending.
js
function longestMountain(arr) {
  let best = 0
  for (let i = 1; i < arr.length - 1; i++) {
    if (arr[i - 1] < arr[i] && arr[i] > arr[i + 1]) {
      let l = i - 1,
        r = i + 1
      while (l > 0 && arr[l - 1] < arr[l]) l--
      while (r < arr.length - 1 && arr[r + 1] < arr[r]) r++
      best = Math.max(best, r - l + 1)
    }
  }
  return best
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
longestMountain([2, 1, 4, 7, 3, 2, 5]) // → 5
longestMountain([2, 2, 2]) // → 0

Back to index


35. Transform and Sort Array

Difficulty: Medium · Time: O(n log n) · Space: O(n)

Replace each element with sum of itself and all smaller elements, then sort.

Approach (step by step):

  1. Sort copy; map each value to prefix sum up to that value using binary search.
js
function transformSort(arr) {
  const sorted = [...arr].sort((a, b) => a - b)
  const prefix = sorted.reduce((acc, x) => {
    acc.push((acc.at(-1) ?? 0) + x)
    return acc
  }, [])
  const rankSum = new Map()
  sorted.forEach((x, i) => {
    if (!rankSum.has(x)) rankSum.set(x, prefix[i])
  })
  return arr.map((x) => rankSum.get(x)).sort((a, b) => a - b)
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
transformSort([2, 1, 3, 1, 2]) // → [2, 3, 4, 6, 6]

Back to index


36. Minimum Swaps To Group All Ones

Difficulty: Medium · Time: O(n) · Space: O(1)

Minimum swaps to bring all 1s together in a contiguous block.

Approach (step by step):

  1. Sliding window of size = count of ones; count zeroes in window.
js
function minSwapsGroupOnes(arr) {
  const ones = arr.filter((x) => x === 1).length
  if (!ones) return 0
  let zeros = 0,
    best = Infinity
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] === 0) zeros++
    if (i >= ones && arr[i - ones] === 0) zeros--
    if (i >= ones - 1) best = Math.min(best, zeros)
  }
  return best
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
minSwapsGroupOnes([1, 0, 0, 1, 0, 1]) // → 1
minSwapsGroupOnes([0, 1, 0, 1, 1, 0, 0]) // → 1

Back to index


37. Minimum Moves To Equalize Array

Difficulty: Medium · Time: O(n) · Space: O(1)

In one move, increment n-1 elements or decrement one. Min moves to equal array.

Approach (step by step):

  1. Equivalent to sum of (max - each element); answer = n*max - sum.
js
function minMovesEqual(arr) {
  const max = Math.max(...arr)
  const sum = arr.reduce((a, b) => a + b, 0)
  return arr.length * max - sum
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
minMovesEqual([1, 2, 3]) // → 3
minMovesEqual([1, 1, 1]) // → 0

Back to index


38. Minimum Indices To Equal Even-Odd Sums

Difficulty: Medium · Time: O(n) · Space: O(1)

Split at index i so sum(even indices) == sum(odd indices); return min i or -1.

Approach (step by step):

  1. Precompute total even/odd sums; walk i updating left/right sums.
js
function minIndexBalance(arr) {
  let even = 0,
    odd = 0
  for (let i = 0; i < arr.length; i++) i % 2 === 0 ? (even += arr[i]) : (odd += arr[i])
  if (even === odd) return 0
  let leftE = arr[0],
    leftO = 0
  for (let i = 1; i < arr.length; i++) {
    const rightE = even - leftE,
      rightO = odd - leftO
    if (leftE + (i % 2 === 0 ? 0 : arr[i]) === rightO + (i % 2 === 0 ? arr[i] : 0)) return i
    if (i % 2 === 0) leftE += arr[i]
    else leftO += arr[i]
  }
  return -1
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
minIndexBalance([2, 4, 3, 1, 5]) // → -1
minIndexBalance([1, 2, 3, 4]) // → -1

Back to index


Hard (39–50)

39. Trapping Rain Water

Difficulty: Hard · Time: O(n) · Space: O(1)

Compute total trapped rain water between bars.

Approach (step by step):

  1. Two pointers with left/right max; move shorter side inward.
js
function trapRainWater(arr) {
  let l = 0,
    r = arr.length - 1,
    lMax = 0,
    rMax = 0,
    water = 0
  while (l < r) {
    if (arr[l] < arr[r]) {
      lMax = Math.max(lMax, arr[l])
      water += lMax - arr[l]
      l++
    } else {
      rMax = Math.max(rMax, arr[r])
      water += rMax - arr[r]
      r--
    }
  }
  return water
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
trapRainWater([0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]) // → 6
trapRainWater([4, 2, 0, 3, 2, 5]) // → 9

Back to index


40. Maximum Circular Subarray Sum

Difficulty: Hard · Time: O(n) · Space: O(1)

Max subarray sum for circular array.

Approach (step by step):

  1. Either normal Kadane or total - min subarray sum (wrap case).
js
function maxCircularSum(arr) {
  const kadane = (a) => {
    let cur = a[0],
      best = 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
  }
  const total = arr.reduce((a, b) => a + b, 0)
  const minSub = (() => {
    let cur = arr[0],
      best = arr[0]
    for (let i = 1; i < arr.length; i++) {
      cur = Math.min(arr[i], cur + arr[i])
      best = Math.min(best, cur)
    }
    return best
  })()
  if (minSub === total) return kadane(arr)
  return Math.max(kadane(arr), total - minSub)
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
maxCircularSum([5, -3, 5]) // → 10
maxCircularSum([3, -1, 2, -1]) // → 4

Back to index


41. Smallest Missing Positive Number

Difficulty: Hard · Time: O(n) · Space: O(1)

First missing positive integer in unsorted array.

Approach (step by step):

  1. Cyclic sort: place value v at index v-1 if 1 ≤ v ≤ n.
js
function firstMissingPositive(arr) {
  const n = arr.length
  for (let i = 0; i < n; i++) {
    while (arr[i] > 0 && arr[i] <= n && arr[arr[i] - 1] !== arr[i]) {
      ;[arr[arr[i] - 1], arr[i]] = [arr[i], arr[arr[i] - 1]]
    }
  }
  for (let i = 0; i < n; i++) if (arr[i] !== i + 1) return i + 1
  return n + 1
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
firstMissingPositive([3, 4, -1, 1]) // → 2
firstMissingPositive([1, 2, 0]) // → 3

Back to index


42. Jump Game

Difficulty: Hard · Time: O(n) · Space: O(1)

Can you reach the last index if arr[i] is max jump length from i?

Approach (step by step):

  1. Track farthest reachable; fail if i > farthest.
js
function canJump(arr) {
  let far = 0
  for (let i = 0; i < arr.length; i++) {
    if (i > far) return false
    far = Math.max(far, i + arr[i])
    if (far >= arr.length - 1) return true
  }
  return true
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
canJump([2, 3, 1, 1, 4]) // → true
canJump([3, 2, 1, 0, 4]) // → false

Back to index


43. Closest Subsequence Sum

Difficulty: Hard · Time: O(n · 2^(n/2)) · Space: O(2^(n/2))

Pick subsequence closest to target; return that sum.

Approach (step by step):

  1. Meet-in-the-middle: enumerate left/right sums, binary search best pair.
js
function closestSubseqSum(arr, target) {
  const sums = (nums) => {
    const out = [0]
    for (const x of nums) {
      const len = out.length
      for (let i = 0; i < len; i++) out.push(out[i] + x)
    }
    return out.sort((a, b) => a - b)
  }
  const mid = Math.floor(arr.length / 2)
  const left = sums(arr.slice(0, mid))
  const right = sums(arr.slice(mid))
  let best = Infinity,
    ans = 0
  for (const a of left) {
    let lo = 0,
      hi = right.length - 1
    while (lo <= hi) {
      const s = a + right[lo]
      if (Math.abs(s - target) < Math.abs(best - target)) {
        best = s
        ans = s
      }
      if (s < target) lo++
      else hi--
    }
  }
  return ans
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
closestSubseqSum([-1, 2, 1], 4) // → 3
closestSubseqSum([2, -1, 0, 1, -3, 3, -3], 2) // → 2

Back to index


44. Smallest Non-Representable Sum

Difficulty: Hard · Time: O(n log n) · Space: O(1)

Smallest positive integer that cannot be formed as sum of subset of array.

Approach (step by step):

  1. Sort positives; extend reachable range [1, res) if next coin ≤ res.
js
function smallestNonRepresentable(arr) {
  const pos = arr.filter((x) => x > 0).sort((a, b) => a - b)
  let res = 1
  for (const x of pos) {
    if (x > res) break
    res += x
  }
  return res
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
smallestNonRepresentable([1, 1, 1, 1]) // → 5
smallestNonRepresentable([1, 2, 5, 10]) // → 4

Back to index


45. Smallest Range Covering K Lists

Difficulty: Hard · Time: O(n log k) · Space: O(k)

Each list is sorted; find smallest range including at least one from each list.

Approach (step by step):

  1. Min-heap on list heads; track window min/max.
js
function smallestRange(lists) {
  const heap = lists.map((list, i) => ({ val: list[0], i, j: 0 }))
  heap.sort((a, b) => a.val - b.val)
  let curMax = Math.max(...heap.map((x) => x.val))
  let best = [-1e9, 1e9]
  while (true) {
    const min = heap[0]
    if (curMax - min.val < best[1] - best[0]) best = [min.val, curMax]
    if (min.j + 1 >= lists[min.i].length) break
    min.j++
    min.val = lists[min.i][min.j]
    curMax = Math.max(curMax, min.val)
    heap.sort((a, b) => a.val - b.val)
  }
  return best
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
smallestRange([
  [4, 10, 15, 24, 26],
  [0, 9, 12, 20],
  [5, 18, 22, 30],
]) // → [20, 24]

Back to index


46. Count Subarrays with K Distinct

Difficulty: Hard · Time: O(n) · Space: O(k)

Count subarrays with exactly k distinct integers.

Approach (step by step):

  1. Use atMost(k) - atMost(k-1) with sliding window frequency map.
js
function subarraysWithKDistinct(arr, k) {
  const atMost = (goal) => {
    const freq = new Map()
    let left = 0,
      count = 0
    for (let right = 0; right < arr.length; right++) {
      freq.set(arr[right], (freq.get(arr[right]) ?? 0) + 1)
      while (freq.size > goal) {
        const l = arr[left++]
        const f = freq.get(l) - 1
        if (f === 0) freq.delete(l)
        else freq.set(l, f)
      }
      count += right - left + 1
    }
    return count
  }
  return atMost(k) - atMost(k - 1)
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
subarraysWithKDistinct([1, 2, 1, 2, 3], 2) // → 7
subarraysWithKDistinct([1, 2, 1, 3, 4], 3) // → 3

Back to index


47. Next Smallest Palindrome

Difficulty: Hard · Time: O(n) · Space: O(1)

Given palindrome digit array, return next smallest palindrome as digit array.

Approach (step by step):

  1. Mirror first half to second; increment middle like next permutation on left half.
js
function nextPalindrome(digits) {
  const n = digits.length
  const half = Math.floor(n / 2)
  const left = digits.slice(0, half)
  let carry = 1
  for (let i = half - 1; i >= 0 && carry; i--) {
    const sum = left[i] + carry
    left[i] = sum % 10
    carry = Math.floor(sum / 10)
  }
  if (carry)
    return Array(n + 1)
      .fill(0)
      .map((_, i) => (i === 0 || i === n ? 1 : 0))
  const out = [...left]
  if (n % 2) out.push(digits[half])
  return [...out, ...left.slice().reverse()]
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
nextPalindrome([1, 2, 2, 1]) // → [2, 1, 1, 2]
nextPalindrome([9, 9, 9]) // → [1, 0, 0, 0, 1]

Back to index


48. Maximum Sum Among All Rotations

Difficulty: Hard · Time: O(n) · Space: O(1)

Max sum of i*arr[i] over all circular rotations.

Approach (step by step):

  1. Derive rotation delta: add (sum - n*last) each step; track max.
js
function maxSumRotations(arr) {
  const n = arr.length
  let sum = 0,
    cur = 0
  for (let i = 0; i < n; i++) {
    sum += arr[i]
    cur += i * arr[i]
  }
  let best = cur
  for (let i = 1; i < n; i++) {
    cur += sum - n * arr[n - i]
    best = Math.max(best, cur)
  }
  return best
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
maxSumRotations([8, 3, 1, 2]) // → 29
maxSumRotations([1, 2, 3]) // → 8

Back to index


49. Two Sum

Difficulty: Easy · Time: O(n) · Space: O(n)

Return indices of two numbers that add up to target.

Approach (step by step):

  1. Hash map stores value → index; for each x check if target-x seen.
js
function twoSum(arr, target) {
  const map = new Map()
  for (let i = 0; i < arr.length; i++) {
    const need = target - arr[i]
    if (map.has(need)) return [map.get(need), i]
    map.set(arr[i], i)
  }
  return []
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
twoSum([2, 7, 11, 15], 9) // → [0, 1]
twoSum([3, 2, 4], 6) // → [1, 2]

Back to index


50. Container With Most Water

Difficulty: Medium · Time: O(n) · Space: O(1)

Max area formed by two lines (heights array) with x-axis.

Approach (step by step):

  1. Two pointers at ends; move shorter side inward.
js
function maxArea(arr) {
  let l = 0,
    r = arr.length - 1,
    best = 0
  while (l < r) {
    best = Math.max(best, Math.min(arr[l], arr[r]) * (r - l))
    if (arr[l] < arr[r]) l++
    else r--
  }
  return best
}

Function calls with output

js
// ── Demo calls — output shown on the right ──
maxArea([1, 8, 6, 2, 5, 4, 8, 3, 7]) // → 49
maxArea([1, 1]) // → 1

Back to index


Summary

LevelCountPatterns
Easy18Two pointers, prefix, single scan
Medium20Sliding window, Kadane, Boyer–Moore
Hard12Meet-in-the-middle, cyclic sort, multi-list heap

Interview Answer

"How do you approach array interview problems?"

Clarify constraints → pick pattern (two pointers, sliding window, prefix/hash, sort+scan) → state time/space → code with edge cases (empty, one element, duplicates).

Next reads: DSA Arrays · Binary Search · Merge Sort

Share this article

XLinkedInFacebook
Kazi Rahamatullah

Written by

Kazi Rahamatullah

FullStack Developer

X / TwitterGitHubLinkedIn

Subscribe to my newsletter

Stay up to date and get notified when I share new contents.

No spam ever, unsubscribe anytime