Top 25 Kotlin Array Problems with Solutions : Master the Fundamentals for 2025

Kotlin Array Problems Cheat Sheet 🚀

This guide covers the most important Kotlin array & algorithm problems for interviews and coding practice. Each problem includes:


1️⃣ Reverse an Array


fun reverseArray(arr: IntArray) {
    var start = 0
    var end = arr.size - 1
    while (start < end) {
        val temp = arr[start]      // **store arr[start] temporarily**
        arr[start] = arr[end]      // **swap arr[start] with arr[end]**
        arr[end] = temp            // **place temp at arr[end]**
        start++                    // **move start forward**
        end--                      // **move end backward**
    }
}

fun main() {
    val arr = intArrayOf(1, 2, 3, 4, 5)
    reverseArray(arr)
    println(arr.joinToString())
}

Output:
Input: [1, 2, 3, 4, 5]
Reversed: [5, 4, 3, 2, 1]

Time: O(n), Space: O(1)

2. Find Max & Min in Array

Scan the array once, updating min and max variables.


fun findMinMax(arr: IntArray): Pair<Int, Int> {
    var min = arr[0]
    var max = arr[0]
    for (num in arr) {
        if (num < min) min = num   // **update min if smaller found**
        if (num > max) max = num   // **update max if larger found**
    }
    return Pair(min, max)
}

fun main() {
    val arr = intArrayOf(3, 1, 7, 0, 9, 5)
    val (min, max) = findMinMax(arr)
    println("Min: $min, Max: $max")
}

Output:
Input: [3,1,7,0,9,5] → Min: 0, Max: 9

Time: O(n), Space: O(1)


3. Cyclically Rotate by 1

Store last element then shift all elements right by 1.


fun rotateByOne(arr: IntArray) {
    val last = arr[arr.size - 1]    // **store last**
    for (i in arr.size - 1 downTo 1) {
        arr[i] = arr[i - 1]         // **shift right**
    }
    arr[0] = last                   // **place last at first**
}

fun main() {
    val arr = intArrayOf(1,2,3,4,5)
    rotateByOne(arr)
    println(arr.joinToString())
}

Output:
Input: [1,2,3,4,5] → Rotated: [5,1,2,3,4]

Time: O(n), Space: O(1)


4. Move Negatives to One Side (Order Not Preserved)

Two-pointer swap: positives swapped with right pointer until all negatives on left.


fun moveNegativesOneSide(arr: IntArray) {
    var left = 0
    var right = arr.size - 1
    while (left <= right) {
        if (arr[left] < 0) left++             // **already negative**
        else {
            val temp = arr[left]
            arr[left] = arr[right]           // **swap positive with right**
            arr[right] = temp
            right--                           // **move right backward**
        }
    }
}

fun main() {
    val arr = intArrayOf(-1, 2, -3, 4, -5)
    moveNegativesOneSide(arr)
    println(arr.joinToString())
}

Output:
Input: [-1,2,-3,4,-5] → Example result: [-1,-5,-3,4,2] (order not guaranteed)

Time: O(n), Space: O(1)


5. Move Negatives (Order Preserved / Stable)

Use another array to copy negatives first then non-negatives (stable partition).


fun stableMoveNegatives(arr: IntArray): IntArray {
    val result = IntArray(arr.size)
    var idx = 0
    for (v in arr) if (v < 0) result[idx++] = v   // **add negatives**
    for (v in arr) if (v >= 0) result[idx++] = v  // **add non-negatives**
    return result
}

fun main() {
    val arr = intArrayOf(-1, 2, -3, 4, -5)
    println(stableMoveNegatives(arr).joinToString())
}

Output:
Input: [-1,2,-3,4,-5] → Result: [-1,-3,-5,2,4]

Time: O(n), Space: O(n) (for result)


6. Rearrange +/- Alternately (O(1) extra space)

Find out-of-place indices and right-rotate subarray to place opposite-signed element — in-place and stable.


fun rearrangeAlternate(arr: IntArray) {
    var outOfPlace = -1
    for (i in arr.indices) {
        if (outOfPlace >= 0) {
            if ((arr[i] >= 0 && arr[outOfPlace] < 0) || (arr[i] < 0 && arr[outOfPlace] >= 0)) {
                val temp = arr[i]
                var j = i
                while (j > outOfPlace) {
                    arr[j] = arr[j - 1]   // **shift right**
                    j--
                }
                arr[outOfPlace] = temp   // **place element**
                outOfPlace = if (i - outOfPlace >= 2) outOfPlace + 2 else -1
            }
        } else {
            if ((arr[i] >= 0 && i % 2 == 1) || (arr[i] < 0 && i % 2 == 0)) outOfPlace = i // **mark**
        }
    }
}

fun main() {
    val arr = intArrayOf(-1, 3, -5, 6, -2, 4, -7, 8)
    rearrangeAlternate(arr)
    println(arr.joinToString())
}

Output:
Input: [-1,3,-5,6,-2,4,-7,8] → Example output: [-1,3,-5,6,-2,4,-7,8] (alternating; extras at end if counts differ)

Time: O(n^2) in worst-case due to shifts, Space: O(1)


7. Three-Way Partition Around a Value (Dutch National Flag)

Use low/mid/high pointers to partition into < pivot, == pivot, > pivot in one pass.


fun threeWayPartition(arr: IntArray, pivot: Int) {
    var low = 0; var mid = 0; var high = arr.size - 1
    while (mid <= high) {
        when {
            arr[mid] < pivot -> {
                val tmp = arr[low]; arr[low] = arr[mid]; arr[mid] = tmp
                low++; mid++
            }
            arr[mid] == pivot -> mid++
            else -> {
                val tmp = arr[mid]; arr[mid] = arr[high]; arr[high] = tmp
                high--
            }
        }
    }
}

fun main() {
    val arr = intArrayOf(2,5,1,2,3,2,4)
    threeWayPartition(arr, 2)
    println(arr.joinToString())
}

Output:
Input: [2,5,1,2,3,2,4], pivot=2 → One valid result: [1,2,2,2,3,5,4]

Time: O(n), Space: O(1)


8. Minimum Swaps to Group Elements ≤ K Together

Sliding window: window size = count(elements ≤ K). Count bad elements (>K) in windows and take min.


fun minSwapsToGroup(arr: IntArray, k: Int): Int {
    val windowSize = arr.count { it <= k }
    var bad = arr.take(windowSize).count { it > k } // **bad in first window**
    var minSwaps = bad
    for (i in windowSize until arr.size) {
        if (arr[i - windowSize] > k) bad--   // **outgoing**
        if (arr[i] > k) bad++                // **incoming**
        minSwaps = minOf(minSwaps, bad)
    }
    return minSwaps
}

fun main() {
    val arr = intArrayOf(2,1,5,6,3)
    println(minSwapsToGroup(arr, 3))
}

Output:
Input: [2,1,5,6,3], K=3 → Min swaps required: 1

Time: O(n), Space: O(1)


9. Merge Two Sorted Arrays In-Place (Gap Method)

Use gap = ceil((n+m)/2) and compare elements at distance gap, swapping when needed; reduce gap progressively.


fun nextGap(gap: Int): Int = if (gap <= 1) 0 else (gap + 1) / 2

fun mergeGap(arr1: IntArray, arr2: IntArray) {
    var n = arr1.size; var m = arr2.size
    var gap = nextGap(n + m)
    while (gap > 0) {
        var i = 0
        while (i + gap < n) {
            if (arr1[i] > arr1[i + gap]) { val t = arr1[i]; arr1[i] = arr1[i + gap]; arr1[i + gap] = t }
            i++
        }
        var j = if (gap > n) gap - n else 0
        while (i < n && j < m) {
            if (arr1[i] > arr2[j]) { val t = arr1[i]; arr1[i] = arr2[j]; arr2[j] = t }
            i++; j++
        }
        j = 0
        while (j + gap < m) {
            if (arr2[j] > arr2[j + gap]) { val t = arr2[j]; arr2[j] = arr2[j + gap]; arr2[j + gap] = t }
            j++
        }
        gap = nextGap(gap)
    }
}

fun main() {
    val a1 = intArrayOf(1,4,7,8,10)
    val a2 = intArrayOf(2,3,9)
    mergeGap(a1, a2)
    println(a1.joinToString() + " | " + a2.joinToString())
}

Output:
Input: arr1=[1,4,7,8,10], arr2=[2,3,9] → Merged view: arr1=[1,2,3,4,7], arr2=[8,9,10]

Time: O((n+m) log(n+m)) approx, Space: O(1)


10. Union of Two Sorted Arrays

Two-pointer traversal; add smaller element, handle equal elements once.


fun unionSorted(arr1: IntArray, arr2: IntArray): List<Int> {
    var i = 0; var j = 0
    val result = mutableListOf<Int>()
    while (i < arr1.size && j < arr2.size) {
        when {
            arr1[i] < arr2[j] -> { result.add(arr1[i]); i++ }
            arr1[i] > arr2[j] -> { result.add(arr2[j]); j++ }
            else -> { result.add(arr1[i]); i++; j++ }
        }
    }
    while (i < arr1.size) result.add(arr1[i++])
    while (j < arr2.size) result.add(arr2[j++])
    return result
}

fun main() {
    val a = intArrayOf(1,3,4,5,7)
    val b = intArrayOf(2,3,5,6)
    println(unionSorted(a,b))
}

Output:
Input: [1,3,4,5,7] & [2,3,5,6] → Union: [1,2,3,3,4,5,5,6,7]

Time: O(n+m), Space: O(n+m)


11. Intersection of Two Sorted Arrays

Two-pointer traversal, add elements only when equal.


fun intersectionSorted(arr1: IntArray, arr2: IntArray): List<Int> {
    var i=0; var j=0
    val res = mutableListOf<Int>()
    while (i < arr1.size && j < arr2.size) {
        when {
            arr1[i] < arr2[j] -> i++
            arr1[i] > arr2[j] -> j++
            else -> { res.add(arr1[i]); i++; j++ }
        }
    }
    return res
}

fun main() {
    val a = intArrayOf(1,3,4,5,7)
    val b = intArrayOf(2,3,5,6)
    println(intersectionSorted(a,b))
}

Output:
Input: [1,3,4,5,7] & [2,3,5,6] → Intersection: [3,5]

Time: O(n+m), Space: O(min(n,m))


12. Two Sum II (Sorted)

Two-pointer method utilising sorted property to find pair in O(n).


fun twoSumSorted(nums: IntArray, target: Int): Pair<Int,Int>? {
    var l = 0; var r = nums.lastIndex
    while (l < r) {
        val s = nums[l] + nums[r]
        if (s == target) return Pair(l+1, r+1) // 1-based
        if (s < target) l++ else r--
    }
    return null
}

fun main() {
    val nums = intArrayOf(2,7,11,15)
    println(twoSumSorted(nums, 9))
}

Output:
Input: [2,7,11,15], target=9 → Indices (1-based): (1,2)

Time: O(n), Space: O(1)


13. Minimum Absolute Difference (Sorted)

In sorted arrays the minimal absolute difference is between consecutive elements.


fun minAbsDiff(sortedArr: IntArray): Int {
    var minDiff = Int.MAX_VALUE
    for (i in 0 until sortedArr.size - 1) {
        minDiff = minOf(minDiff, kotlin.math.abs(sortedArr[i+1] - sortedArr[i])) // **consec diff**
    }
    return minDiff
}

fun main() {
    val arr = intArrayOf(1,3,6,10,15)
    println(minAbsDiff(arr))
}

Output:
Input: [1,3,6,10,15] → Minimum absolute difference = 2 (between 1 & 3)

Time: O(n), Space: O(1)


14. Max Sum Subarray of Size K (Fixed Window)

Sliding window: maintain a running sum for window size k and update max.


fun maxSumSubarray(arr: IntArray, k: Int): Int {
    var windowSum = 0
    var maxSum = Int.MIN_VALUE

    for (i in 0 until k) windowSum += arr[i]  // **initial window**
    maxSum = windowSum

    for (i in k until arr.size) {
        windowSum += arr[i] - arr[i - k]     // **slide**
        maxSum = maxOf(maxSum, windowSum)    // **update**
    }
    return maxSum
}

fun main() {
    val arr = intArrayOf(2,1,5,1,3,2)
    println(maxSumSubarray(arr, 3))
}

Output:
Input: [2,1,5,1,3,2], k=3 → Max sum = 9

Time: O(n), Space: O(1)


15. Best Time to Buy and Sell Stock I

Keep track of the minimum price seen so far and compute best profit by selling today.


fun maxProfit(prices: IntArray): Int {
    var minPrice = Int.MAX_VALUE
    var maxProfit = 0
    for (p in prices) {
        minPrice = minOf(minPrice, p)                // **track min price**
        maxProfit = maxOf(maxProfit, p - minPrice)   // **update profit**
    }
    return maxProfit
}

fun main() {
    val prices = intArrayOf(7,1,5,3,6,4)
    println(maxProfit(prices))
}

Output:
Input: [7,1,5,3,6,4] → Max profit = 5 (buy at 1, sell at 6)

Time: O(n), Space: O(1)


16. Two Sum (HashMap)

Use a map to store seen numbers and their indices; check complement each iteration.


fun twoSum(nums: IntArray, target: Int): IntArray {
    val map = mutableMapOf<Int, Int>()
    for (i in nums.indices) {
        val complement = target - nums[i]
        if (map.containsKey(complement)) return intArrayOf(map[complement]!!, i)
        map[nums[i]] = i
    }
    return intArrayOf()
}

fun main() {
    val nums = intArrayOf(2,7,11,15)
    println(twoSum(nums, 9).joinToString())
}

Output:
Input: [2,7,11,15], target=9 → Indices (0-based): [0,1]

Time: O(n), Space: O(n)


17. Move Zeroes (Alternative swap-based)

Swap non-zero with left pointer to minimize writes.


fun moveZeroesSwap(nums: IntArray) {
    var left = 0
    for (right in nums.indices) {
        if (nums[right] != 0) {
            val t = nums[left]; nums[left] = nums[right]; nums[right] = t  // **swap**
            left++
        }
    }
}

fun main() {
    val nums = intArrayOf(0,1,0,3,12)
    moveZeroesSwap(nums)
    println(nums.joinToString())
}

Output:
Input: [0,1,0,3,12] → Result: [1,3,12,0,0]

Time: O(n), Space: O(1)


18. Remove Duplicates from Sorted Array

Use two pointers: write pointer for last unique element.


fun removeDuplicates(nums: IntArray): Int {
    if (nums.isEmpty()) return 0
    var write = 0
    for (read in 1 until nums.size) {
        if (nums[read] != nums[write]) {
            write++
            nums[write] = nums[read]   // **store unique**
        }
    }
    return write + 1
}

fun main() {
    val nums = intArrayOf(1,1,2,2,3,4,4,5)
    val newLen = removeDuplicates(nums)
    println("NewLen: $newLen, Unique array: ${nums.take(newLen)}")
}

Output:
Input: [1,1,2,2,3,4,4,5] → NewLen: 5, Unique: [1,2,3,4,5]

Time: O(n), Space: O(1)


19. Range Sum Query – Immutable (Prefix Sum)

Precompute prefix sums so range queries are O(1).


class NumArray(nums: IntArray) {
    private val prefix = IntArray(nums.size + 1)
    init {
        for (i in nums.indices) prefix[i+1] = prefix[i] + nums[i] // **build prefix**
    }
    fun sumRange(l: Int, r: Int) = prefix[r+1] - prefix[l] // **range sum**
}

fun main() {
    val na = NumArray(intArrayOf(-2,0,3,-5,2,-1))
    println(na.sumRange(0,2))
}

Output:
Input: [-2,0,3,-5,2,-1], sumRange(0,2) → 1

Preprocess: O(n), Query: O(1), Space: O(n)


20. Single Number (XOR)

XOR all numbers; duplicates cancel each other leaving single number.


fun singleNumber(nums: IntArray): Int {
    var res = 0
    for (n in nums) res = res xor n  // **duplicates cancel**
    return res
}

fun main() {
    val nums = intArrayOf(4,1,2,1,2)
    println(singleNumber(nums))
}

Output:
Input: [4,1,2,1,2] → Single number: 4

Time: O(n), Space: O(1)


21. Missing Number

Use sum formula or XOR to find the missing number from 0..n.


fun missingNumber(nums: IntArray): Int {
    val n = nums.size
    val total = n * (n + 1) / 2
    return total - nums.sum() // **missing = total - actual**
}

fun main() {
    val nums = intArrayOf(3,0,1)
    println(missingNumber(nums))
}

Output:
Input: [3,0,1] → Missing number: 2

Time: O(n), Space: O(1)


22. Find All Numbers Disappeared in an Array

Mark visited indices by negation; positive entries at the end correspond to missing numbers.


fun findDisappearedNumbers(nums: IntArray): List<Int> {
    for (i in nums.indices) {
        val idx = kotlin.math.abs(nums[i]) - 1
        if (nums[idx] > 0) nums[idx] = -nums[idx]  // **mark visited**
    }
    val res = mutableListOf<Int>()
    for (i in nums.indices) if (nums[i] > 0) res.add(i + 1) // **positive -> missing**
    return res
}

fun main() {
    val nums = intArrayOf(4,3,2,7,8,2,3,1)
    println(findDisappearedNumbers(nums))
}

Output:
Input: [4,3,2,7,8,2,3,1] → Missing: [5,6]

Time: O(n), Space: O(1) (excluding output list)


23. Find Kth Missing Positive Number

Traverse natural numbers and array pointers to count missing numbers until k-th is found.


fun findKthPositive(arr: IntArray, k: Int): Int {
    var missing = k
    var current = 1
    var i = 0
    while (true) {
        if (i < arr.size && arr[i] == current) i++   // **present**
        else {
            missing--                                 // **missing**
            if (missing == 0) return current
        }
        current++
    }
}

fun main() {
    val arr = intArrayOf(2,3,4,7,11)
    println(findKthPositive(arr, 5))
}

Output:
Input: [2,3,4,7,11], k=5 → 9

Time: O(n + k), Space: O(1)


24. Next Greater Element I

Use a monotonic stack to compute the next greater for all elements in nums2, then map answers for nums1.


fun nextGreaterElement(nums1: IntArray, nums2: IntArray): IntArray {
    val map = mutableMapOf<Int, Int>()
    val stack = ArrayDeque<Int>()
    for (n in nums2) {
        while (stack.isNotEmpty() && stack.last() < n) {
            map[stack.removeLast()] = n  // **map smaller -> next greater**
        }
        stack.addLast(n)
    }
    while (stack.isNotEmpty()) map[stack.removeLast()] = -1
    return nums1.map { map[it] ?: -1 }.toIntArray()
}

fun main() {
    val nums1 = intArrayOf(4,1,2)
    val nums2 = intArrayOf(1,3,4,2)
    println(nextGreaterElement(nums1, nums2).joinToString())
}

Output:
Input: nums1=[4,1,2], nums2=[1,3,4,2] → Output: [-1,3,-1]

Time: O(n + m), Space: O(n)


Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top