Walk the array once, storing seen values in a lookup table. When the complement is already present, the result indices are known.

Algorithm

Basic Implementation

basic.kt
fun main() {
	val arr = intArrayOf(2, 7, 11, 4, 5)
	val target = 9
	val seen = mutableMapOf<Int, Int>()
	var first = -1
	var second = -1
	for (i in arr.indices) {
		val value = arr[i]
		val need = target - value
		if (seen.containsKey(need)) {
			first = seen[need]!!
			second = i
			break
		}
		seen[value] = i
	}
	println("[$first, $second]")
}

Complexity

  • Time: O(n) average
  • Space: O(n)

Implementation notes

  • Kotlin stores the input as a primitive IntArray and iterates indexes with for (i in arr.indices), so each arr[i] read yields a non-null Int.
  • arr, target, and seen are val bindings; seen still mutates because it is created with mutableMapOf<Int, Int>().
  • first and second are var Int sentinels initialized to -1 and replaced only after a successful complement lookup.
  • Each loop binds value = arr[i] and computes need = target - value before updating the map, so the current index cannot pair with itself.
  • The map lookup uses seen.containsKey(need) before seen[need]!!; the non-null assertion is guarded by the membership check in this source.
  • Misses update the map with seen[value] = i, storing value-to-index pairs as Int keys and Int values.
  • The trace records {} then {2: 0} after i=0; at i=1, need is 2, the lookup hits, and the result becomes [0, 1].
  • println("[$first, $second]") formats the two result indexes directly, producing [0, 1].
execution replay The checked-in replay follows the language-neutral state table for `array-two-sum-hash`.
cross-language comparison This Kotlin DSA version keeps the same data and final output as every other DSA book in this wave.