I'm learning Golang and have been trying to get 100% on the following Hackerrank practice challenge: Climbing the Leaderboard
The code passes ~8 of 11 tests. The Hackerrank tests are time-bound and my code is not efficient enough to past the most intensive tests.
I'm removing duplicates from the scores using a map. Then work through each of Alice's scores to find the index of each one by doing a binary search. Given that Alice's scored are sorted, I re-use the index for the next search.
Any ideas?
package main
import (
"fmt"
)
func main() {
// example 1
scores := []int32{100, 100, 50, 40, 40, 20, 10}
alice := []int32{5, 25, 50, 120}
r := climbingLeaderboard(scores, alice)
for a, v := range r {
fmt.Printf("Position: %d alice[a]: %d\n", v, alice[a])
}
fmt.Printf("\n")
}
func removeDuplicates(a []int32) []int32 {
r := []int32{}
seen := map[int32]int32{}
for _, val := range a {
if _, ok := seen[val]; !ok {
r = append(r, val)
seen[val] = val
}
}
return r
}
func getMidPoint(start, end int) int {
i := end - start
if i%2 == 0 {
return i/2 + start
}
return (i+1)/2 + start
}
// 100 100 50 40 40 20 10
// 100 50 40 20 10
// 0 1 2 3 4
func binarySearch(scores []int32, v int32, i int) int {
var mid int
start := 0
end := i
for true {
if end-start == 1 {
//fmt.Printf("1 - v: %d start: %d end %d\n", v, start, end)
if v < scores[end] {
return end + 2
} else if v < scores[start] {
return start + 2
}
return 1
}
if end == 0 {
return 1
}
mid = getMidPoint(start, end)
if v > scores[mid] {
end = mid
} else if v < scores[mid] {
start = mid
} else {
// v == scores[mid]
//fmt.Printf("2 - v: %d start: %d end %d\n", v, start, end)
return mid + 1
}
}
return end
}
// attempt 3 - binary search
func climbingLeaderboard(originalScores []int32, alice []int32) []int32 {
r := make([]int32, len(alice))
//create scores and remove dups
scores := removeDuplicates(originalScores)
i := len(scores)
for a, v := range alice {
// fmt.Printf("1 - i: %d a: %d alice[a]: %d\n", i, a, alice[a])
i = binarySearch(scores, v, i-1)
r[a] = int32(i)
}
return r
}
panic
on test cases 6, 8 and/or 9. \$\endgroup\$strconv.ParseInt
fails on an empty string. Most other languages (that I looked at) were far more tolerant for this case. The parsing code can be adapted to usefmt.Fscan
to get the same behavior.as the other languages (it even simplyfies the parsing code a bit). \$\endgroup\$scoresItemTemp, err := strconv.ParseInt(scoresTemp[i], 10, 64)
\$\endgroup\$reader := bufio.NewReaderSize(os.Stdin, 1024*1024*3)
. Previously it couldn't read in all of the input so I was seeing this:int(scoresCount): 200000 len(scoresTemp): 104858
. It's still failing test 8 with an ` index out of range` error whenint(scoresCount): 200000 len(scoresTemp): 200000
\$\endgroup\$