Skip to content

K Closest Elements

Implementation

package main

import (
    "fmt"
    "math"
)

type Heap struct {
    arr []Pair
}

type Pair struct {
    diff int
    idx  int
}

func (mh *Heap) insert(diff, idx int) bool {

    mh.arr = append(mh.arr, Pair{diff: diff, idx: idx})
    i := len(mh.arr) - 1
    for i > 0 && mh.arr[parent(i)].diff < mh.arr[i].diff {
        mh.arr[parent(i)], mh.arr[i] = mh.arr[i], mh.arr[parent(i)]
        i = parent(i)
    }

    return true
}

func (h *Heap) pop() Pair {
    val := h.peak()
    lastIdx := len(h.arr) - 1
    h.arr[0] = h.arr[lastIdx]
    h.arr = h.arr[:lastIdx]
    h.heapify(0)
    return val
}

func (h *Heap) peak() Pair {
    return h.arr[0]
}

func (h *Heap) isEmpty() bool {
    return len(h.arr) == 0
}

func (h *Heap) heapify(i int) {
    leftIdx := left(i)
    rightIdx := right(i)
    maxIdx := i
    if leftIdx <= len(h.arr)-1 && h.arr[leftIdx].diff > h.arr[i].diff {
        maxIdx = leftIdx
    }

    if rightIdx <= len(h.arr)-1 && h.arr[rightIdx].diff > h.arr[maxIdx].diff {
        maxIdx = rightIdx
    }
    if maxIdx == i {
        return
    }
    h.arr[i], h.arr[maxIdx] = h.arr[maxIdx], h.arr[i]
    h.heapify(maxIdx)
}

func left(i int) int {
    return 2*i + 1
}

func right(i int) int {
    return 2*i + 2
}
func parent(i int) int {
    return (i - 1) / 2
}

func kClosestElements(arr []int, x, k int) []int {
    res := make([]int, k)

    heap := &Heap{}
    for i := 0; i < k; i++ {
        diff := int(math.Abs(float64(arr[i] - x)))
        heap.insert(diff, i)
    }

    for i := k; i < len(arr); i++ {
        diff := int(math.Abs(float64(arr[i] - x)))
        if heap.peak().diff > diff {
            heap.pop()
            heap.insert(diff, i)
        }
    }
    idx := 0
    for !heap.isEmpty() {
        res[idx] = arr[heap.pop().idx]
        idx++
    }

    return res
}

func main() {
    arr := []int{30, 40, 32, 33, 36, 37}
    res := kClosestElements(arr, 38, 3)
    fmt.Println(res)
}