diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..efb9808
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,24 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..ecbfafa
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,4 @@
+lint:
+ golangci-lint run ./...
+
+.PHONY: lint
diff --git a/create.sh b/create.sh
new file mode 100755
index 0000000..cd8458f
--- /dev/null
+++ b/create.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+num=$1
+
+echo "$num" | grep -q "^[1-9][0-9]\{,4\}$" || {
+ echo "Err: no valid number given" >&2
+ exit 1
+}
+
+parent=$((num / 100))
+pdir="solutions/${parent}/q${num}"
+sol_file="${pdir}/solution.go"
+
+if [ -f "$sol_file" ]; then
+ exit 0
+fi
+
+echo "Creating template for question No. $num" >&2
+mkdir -pv "$pdir"
+echo "package q$num" > "$sol_file"
+echo "Created $sol_file"
diff --git a/go.mod b/go.mod
index e062fa1..9e38376 100644
--- a/go.mod
+++ b/go.mod
@@ -1,3 +1,15 @@
module leetcode-go
go 1.25.5
+
+require (
+ github.com/emirpasic/gods/v2 v2.0.0-alpha
+ github.com/k0kubun/pp/v3 v3.5.0
+)
+
+require (
+ github.com/mattn/go-colorable v0.1.14 // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
+ golang.org/x/sys v0.29.0 // indirect
+ golang.org/x/text v0.26.0 // indirect
+)
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..0aa4e6a
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,13 @@
+github.com/emirpasic/gods/v2 v2.0.0-alpha h1:dwFlh8pBg1VMOXWGipNMRt8v96dKAIvBehtCt6OtunU=
+github.com/emirpasic/gods/v2 v2.0.0-alpha/go.mod h1:W0y4M2dtBB9U5z3YlghmpuUhiaZT2h6yoeE+C1sCp6A=
+github.com/k0kubun/pp/v3 v3.5.0 h1:iYNlYA5HJAJvkD4ibuf9c8y6SHM0QFhaBuCqm1zHp0w=
+github.com/k0kubun/pp/v3 v3.5.0/go.mod h1:5lzno5ZZeEeTV/Ky6vs3g6d1U3WarDrH8k240vMtGro=
+github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
+github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
+golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
+golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
diff --git a/solutions/0/q15/solution.go b/solutions/0/q15/solution.go
new file mode 100644
index 0000000..69d9fcd
--- /dev/null
+++ b/solutions/0/q15/solution.go
@@ -0,0 +1,65 @@
+package q15
+
+import "slices"
+
+func sortAndDedup3(nums []int) []int {
+ slices.Sort(nums)
+ head, dup := 0, 0
+ for i := 1; i < len(nums); i++ {
+ if nums[i] == nums[head] {
+ dup++
+ } else {
+ dup = 0
+ }
+ if dup < 3 {
+ head++
+ nums[head] = nums[i]
+ }
+ }
+ return nums[:head+1]
+}
+
+func threeSum(nums []int) [][]int {
+ nums = sortAndDedup3(nums)
+ ret := [][]int{}
+
+ appendResult := func(a, b, c int) {
+ triplet := []int{a, b, c}
+ if len(ret) > 0 && slices.Equal(triplet, ret[len(ret)-1]) {
+ return
+ }
+ ret = append(ret, triplet)
+ }
+
+ for i := 0; i < len(nums)-2; i++ {
+ if nums[i] > 0 {
+ break
+ }
+ wants := -nums[i]
+ l, r := i+1, len(nums)-1
+ for l < r {
+ for l < r && nums[l]+nums[r] > wants {
+ r--
+ }
+ if l < r && nums[l]+nums[r] == wants {
+ appendResult(nums[i], nums[l], nums[r])
+ r--
+ }
+ for l < r && nums[l]+nums[r] < wants {
+ l++
+ }
+ if l < r && nums[l]+nums[r] == wants {
+ appendResult(nums[i], nums[l], nums[r])
+ l++
+ }
+ }
+
+ // skip same numbers
+ for ; i < len(nums)-2 && nums[i] == nums[i+1]; i++ {
+ }
+ }
+
+ return ret
+}
+
+var _ = threeSum
diff --git a/solutions/0/q17/solution.go b/solutions/0/q17/solution.go
new file mode 100644
index 0000000..632e70d
--- /dev/null
+++ b/solutions/0/q17/solution.go
@@ -0,0 +1,39 @@
+package q17
+
+var alphabets = [][]byte{
+ []byte("abc"),
+ []byte("def"),
+ []byte("ghi"),
+ []byte("jkl"),
+ []byte("mno"),
+ []byte("pqrs"),
+ []byte("tuv"),
+ []byte("wxyz"),
+}
+
+func combinations(offsets []int, i int, buffer []byte, strings []string) []string {
+ if buffer == nil {
+ buffer = make([]byte, len(offsets))
+ }
+
+ if i == len(offsets) {
+ return append(strings, string(buffer))
+ }
+
+ for _, c := range alphabets[offsets[i]] {
+ buffer[i] = c
+ strings = combinations(offsets, i+1, buffer, strings)
+ }
+ return strings
+}
+
+func letterCombinations(digits string) []string {
+ offsets := make([]int, len(digits))
+ for i := range len(digits) {
+ offsets[i] = int(digits[i] - '2')
+ }
+
+ return combinations(offsets, 0, nil, []string{})
+}
+
+var _ = letterCombinations
diff --git a/solutions/0/q20/solution.go b/solutions/0/q20/solution.go
new file mode 100644
index 0000000..254d63b
--- /dev/null
+++ b/solutions/0/q20/solution.go
@@ -0,0 +1,32 @@
+package q20
+
+func isValid(s string) bool {
+ stack := make([]byte, 0, len(s)/2)
+
+ for i := range len(s) {
+ switch s[i] {
+ case '(', '[', '{':
+ stack = append(stack, s[i])
+ case ')':
+ if len(stack) == 0 || stack[len(stack)-1] != '(' {
+ return false
+ }
+ stack = stack[:len(stack)-1]
+
+ case ']':
+ if len(stack) == 0 || stack[len(stack)-1] != '[' {
+ return false
+ }
+ stack = stack[:len(stack)-1]
+
+ case '}':
+ if len(stack) == 0 || stack[len(stack)-1] != '{' {
+ return false
+ }
+ stack = stack[:len(stack)-1]
+ }
+ }
+ return len(stack) == 0
+}
+
+var _ = isValid
diff --git a/solutions/0/q35/solution.go b/solutions/0/q35/solution.go
new file mode 100644
index 0000000..15f6011
--- /dev/null
+++ b/solutions/0/q35/solution.go
@@ -0,0 +1,19 @@
+package q35
+
+func searchInsert(nums []int, target int) int {
+ l, r := 0, len(nums)
+ for l < r {
+ mid := (l + r) / 2
+ switch {
+ case nums[mid] == target:
+ return mid
+ case nums[mid] > target:
+ r = mid
+ default:
+ l = mid + 1
+ }
+ }
+ return l
+}
+
+var _ = searchInsert
diff --git a/solutions/q36/solution.go b/solutions/0/q36/solution.go
similarity index 100%
rename from solutions/q36/solution.go
rename to solutions/0/q36/solution.go
diff --git a/solutions/0/q53/solution.go b/solutions/0/q53/solution.go
new file mode 100644
index 0000000..af32086
--- /dev/null
+++ b/solutions/0/q53/solution.go
@@ -0,0 +1,18 @@
+package q53
+
+import "math"
+
+func maxSubArray(nums []int) int {
+ sum := 0
+ minSubstract := 0
+ maxSubArr := math.MinInt
+ for i := range nums {
+ sum += nums[i]
+ nums[i] = sum
+ maxSubArr = max(maxSubArr, nums[i]-minSubstract)
+ minSubstract = min(minSubstract, nums[i])
+ }
+ return maxSubArr
+}
+
+var _ = maxSubArray
diff --git a/solutions/0/q66/solution.go b/solutions/0/q66/solution.go
new file mode 100644
index 0000000..fdcfb96
--- /dev/null
+++ b/solutions/0/q66/solution.go
@@ -0,0 +1,22 @@
+package q66
+
+func plusOne(digits []int) []int {
+ digits[len(digits)-1]++
+ for i := len(digits) - 1; i > 0; i-- {
+ if digits[i] > 9 {
+ digits[i] -= 10
+ digits[i-1]++
+ } else {
+ break
+ }
+ }
+ if digits[0] > 9 {
+ digits[0] -= 10
+ ret := make([]int, 0, len(digits)+1)
+ ret = append(ret, 1)
+ return append(ret, digits...)
+ }
+ return digits
+}
+
+var _ = plusOne
diff --git a/solutions/0/q67/solution.go b/solutions/0/q67/solution.go
new file mode 100644
index 0000000..b1618ef
--- /dev/null
+++ b/solutions/0/q67/solution.go
@@ -0,0 +1,28 @@
+package q67
+
+func toDigit(byt byte) uint8 { return byt - '0' }
+func toByte(digit uint8) byte { return '0' + digit }
+
+func addBinary(a string, b string) string {
+ lenA, lenB := len(a), len(b)
+ ret := make([]byte, max(lenA, lenB)+1)
+ var carry uint8
+ for i := range ret {
+ d := carry
+ if i < lenA {
+ d += toDigit(a[lenA-i-1])
+ }
+ if i < lenB {
+ d += toDigit(b[lenB-i-1])
+ }
+ carry = d / 2
+ ret[len(ret)-i-1] = toByte(d % 2)
+ }
+
+ if ret[0] != '1' {
+ return string(ret[1:])
+ }
+ return string(ret)
+}
+
+var _ = addBinary
diff --git a/solutions/0/q69/solution.go b/solutions/0/q69/solution.go
new file mode 100644
index 0000000..f02eb65
--- /dev/null
+++ b/solutions/0/q69/solution.go
@@ -0,0 +1,26 @@
+package q69
+
+func mySqrt(x int) int {
+ if x < 2 {
+ return x
+ }
+ l, r := 0, x/2+1
+ for l < r {
+ m := (l + r) / 2
+ sq := m * m
+ switch {
+ case sq == x:
+ return m
+ case sq < x:
+ if (m+1)*(m+1) > x {
+ return m
+ }
+ l = m + 1
+ case sq > x:
+ r = m
+ }
+ }
+ return -1
+}
+
+var _ = mySqrt
diff --git a/solutions/0/q70/solution.go b/solutions/0/q70/solution.go
new file mode 100644
index 0000000..540545d
--- /dev/null
+++ b/solutions/0/q70/solution.go
@@ -0,0 +1,24 @@
+package q70
+
+func nWays(n, i int, cache []int) int {
+ if i == n {
+ return 1
+ }
+ if i > n {
+ return 0
+ }
+ if cache == nil {
+ cache = make([]int, n)
+ } else if cache[i] != 0 {
+ return cache[i]
+ }
+ ret := nWays(n, i+1, cache) + nWays(n, i+2, cache)
+ cache[i] = ret
+ return ret
+}
+
+func climbStairs(n int) int {
+ return nWays(n, 0, nil)
+}
+
+var _ = climbStairs
diff --git a/solutions/0/q9/solution.go b/solutions/0/q9/solution.go
new file mode 100644
index 0000000..faf307a
--- /dev/null
+++ b/solutions/0/q9/solution.go
@@ -0,0 +1,18 @@
+package q9
+
+import "strconv"
+
+func isPalindrome(x int) bool {
+ if x < 0 {
+ return false
+ }
+ str := strconv.FormatInt(int64(x), 10)
+ for i := range len(str) / 2 {
+ if str[i] != str[len(str)-1-i] {
+ return false
+ }
+ }
+ return true
+}
+
+var _ = isPalindrome
diff --git a/solutions/1/q104/solution.go b/solutions/1/q104/solution.go
new file mode 100644
index 0000000..78fa9ca
--- /dev/null
+++ b/solutions/1/q104/solution.go
@@ -0,0 +1,20 @@
+package q104
+
+type TreeNode struct {
+ Val int
+ Left *TreeNode
+ Right *TreeNode
+}
+
+func md(d int, node *TreeNode) int {
+ if node == nil {
+ return d - 1
+ }
+ return max(md(d+1, node.Left), md(d+1, node.Right))
+}
+
+func maxDepth(root *TreeNode) int {
+ return md(1, root)
+}
+
+var _ = maxDepth
diff --git a/solutions/1/q108/solution.go b/solutions/1/q108/solution.go
new file mode 100644
index 0000000..2de7147
--- /dev/null
+++ b/solutions/1/q108/solution.go
@@ -0,0 +1,26 @@
+package q108
+
+type TreeNode struct {
+ Val int
+ Left *TreeNode
+ Right *TreeNode
+}
+
+func sortedArrayToBST(nums []int) *TreeNode {
+ if len(nums) == 0 {
+ return nil
+ }
+ if len(nums) == 1 {
+ return &TreeNode{Val: nums[0]}
+ }
+
+ l, r := nums[:len(nums)/2], nums[len(nums)/2+1:]
+ m := nums[len(nums)/2]
+ return &TreeNode{
+ Val: m,
+ Left: sortedArrayToBST(l),
+ Right: sortedArrayToBST(r),
+ }
+}
+
+var _ = sortedArrayToBST
diff --git a/solutions/1/q120/solution.go b/solutions/1/q120/solution.go
new file mode 100644
index 0000000..5978b01
--- /dev/null
+++ b/solutions/1/q120/solution.go
@@ -0,0 +1,14 @@
+package q120
+
+func minimumTotal(triangle [][]int) int {
+ size := len(triangle)
+
+ for row := size - 2; row >= 0; row-- {
+ for i := range triangle[row] {
+ triangle[row][i] += min(triangle[row+1][i], triangle[row+1][i+1])
+ }
+ }
+ return triangle[0][0]
+}
+
+var _ = minimumTotal
diff --git a/solutions/q125/solution.go b/solutions/1/q125/solution.go
similarity index 100%
rename from solutions/q125/solution.go
rename to solutions/1/q125/solution.go
diff --git a/solutions/q134/solution.go b/solutions/1/q134/solution.go
similarity index 100%
rename from solutions/q134/solution.go
rename to solutions/1/q134/solution.go
diff --git a/solutions/q134/solution_test.go b/solutions/1/q134/solution_test.go
similarity index 100%
rename from solutions/q134/solution_test.go
rename to solutions/1/q134/solution_test.go
diff --git a/solutions/q135/solution.go b/solutions/1/q135/solution.go
similarity index 100%
rename from solutions/q135/solution.go
rename to solutions/1/q135/solution.go
diff --git a/solutions/1/q136/solution.go b/solutions/1/q136/solution.go
new file mode 100644
index 0000000..f1a8404
--- /dev/null
+++ b/solutions/1/q136/solution.go
@@ -0,0 +1,11 @@
+package q136
+
+func singleNumber(nums []int) int {
+ x := 0
+ for _, num := range nums {
+ x ^= num
+ }
+ return x
+}
+
+var _ = singleNumber
diff --git a/solutions/1/q141/solution.go b/solutions/1/q141/solution.go
new file mode 100644
index 0000000..e927c9f
--- /dev/null
+++ b/solutions/1/q141/solution.go
@@ -0,0 +1,28 @@
+package q141
+
+type ListNode struct {
+ Val int
+ Next *ListNode
+}
+
+func hasCycle(head *ListNode) bool {
+ if head == nil {
+ return false
+ }
+
+ p1, p2 := head, head
+ for {
+ for range 2 {
+ p2 = p2.Next
+ switch p2 {
+ case nil:
+ return false
+ case p1:
+ return true
+ }
+ }
+ p1 = p1.Next
+ }
+}
+
+var _ = hasCycle
diff --git a/solutions/q150/solution.go b/solutions/1/q150/solution.go
similarity index 100%
rename from solutions/q150/solution.go
rename to solutions/1/q150/solution.go
diff --git a/solutions/1/q190/solution.go b/solutions/1/q190/solution.go
new file mode 100644
index 0000000..31c77df
--- /dev/null
+++ b/solutions/1/q190/solution.go
@@ -0,0 +1,13 @@
+package q190
+
+func reverseBits(n int) int {
+ ret := 0
+ for i := range 32 {
+ if n|(1< 0; n >>= 1 {
+ if n|1 == n {
+ num++
+ }
+ }
+ return num
+}
+
+var _ = hammingWeight
diff --git a/solutions/1/q199/solution.go b/solutions/1/q199/solution.go
new file mode 100644
index 0000000..3ee35a9
--- /dev/null
+++ b/solutions/1/q199/solution.go
@@ -0,0 +1,37 @@
+package q199
+
+type TreeNode struct {
+ Val int
+ Left *TreeNode
+ Right *TreeNode
+}
+
+func rightSideView(root *TreeNode) []int {
+ ret := []int{}
+
+ type qElem struct {
+ height int
+ node *TreeNode
+ }
+
+ queue := []qElem{{0, root}}
+ var last *qElem
+ for ; len(queue) > 0; queue = queue[1:] {
+ cur := &queue[0]
+ if cur.node == nil {
+ continue
+ }
+ if last != nil && last.height < cur.height {
+ ret = append(ret, last.node.Val)
+ }
+ last = cur
+ queue = append(queue, qElem{cur.height + 1, cur.node.Left}, qElem{cur.height + 1, cur.node.Right})
+ }
+ if last != nil {
+ ret = append(ret, last.node.Val)
+ }
+
+ return ret
+}
+
+var _ = rightSideView
diff --git a/solutions/2/q200/solution.go b/solutions/2/q200/solution.go
new file mode 100644
index 0000000..9564d9a
--- /dev/null
+++ b/solutions/2/q200/solution.go
@@ -0,0 +1,31 @@
+package q200
+
+const (
+ VISITED byte = '.'
+ LAND byte = '1'
+)
+
+func traverse(grid [][]byte, x, y int) int {
+ if x < 0 || y < 0 || x >= len(grid[0]) || y >= len(grid) || grid[y][x] != LAND {
+ return 0
+ }
+
+ grid[y][x] = VISITED
+ traverse(grid, x+1, y)
+ traverse(grid, x-1, y)
+ traverse(grid, x, y+1)
+ traverse(grid, x, y-1)
+ return 1
+}
+
+func numIslands(grid [][]byte) int {
+ count := 0
+ for y := range grid {
+ for x := range grid[y] {
+ count += traverse(grid, x, y)
+ }
+ }
+ return count
+}
+
+var _ = numIslands
diff --git a/solutions/2/q208/solution.go b/solutions/2/q208/solution.go
new file mode 100644
index 0000000..87c3ca2
--- /dev/null
+++ b/solutions/2/q208/solution.go
@@ -0,0 +1,105 @@
+package q208
+
+type tNode struct {
+ str string
+ childs [26]*tNode
+ hasWord bool
+}
+
+func (n *tNode) index() int { return index(n.str) }
+
+func (n *tNode) split(prefixLen int) (*tNode, *tNode) {
+ if len(n.str) < prefixLen {
+ panic("cannot split node")
+ }
+ if len(n.str) == prefixLen {
+ return n, nil
+ }
+
+ prefix := n.str[:prefixLen]
+ n.str = n.str[prefixLen:]
+ p := &tNode{str: prefix}
+ p.childs[n.index()] = n
+ return p, n
+}
+
+func commonPrefix(a, b string) int {
+ minLen := min(len(a), len(b))
+ for i := range minLen {
+ if a[i] != b[i] {
+ return i
+ }
+ }
+ return minLen
+}
+
+func index(str string) int {
+ if len(str) > 0 {
+ return int(str[0] - 'a')
+ }
+ return -1 // root
+}
+
+type Trie struct {
+ root *tNode
+}
+
+func Constructor() Trie {
+ return Trie{
+ root: &tNode{},
+ }
+}
+
+func (t *Trie) Insert(word string) {
+ node := t.root
+ for len(word) > 0 {
+ idx := index(word)
+ next := node.childs[idx]
+ if next != nil {
+ pflen := commonPrefix(word, next.str)
+ next, _ = next.split(pflen)
+ node.childs[next.index()] = next
+ word = word[pflen:]
+ } else {
+ next = &tNode{str: word}
+ word = ""
+ node.childs[idx] = next
+ }
+ node = next
+ }
+ node.hasWord = true
+}
+
+func (t *Trie) Search(word string) bool {
+ node := t.root
+ for len(word) > 0 {
+ next := node.childs[index(word)]
+ if next == nil {
+ return false
+ }
+ pflen := commonPrefix(word, next.str)
+ if pflen != len(next.str) {
+ return false
+ }
+ word = word[pflen:]
+ node = next
+ }
+ return node.hasWord
+}
+
+func (t *Trie) StartsWith(prefix string) bool {
+ node := t.root
+ for len(prefix) > 0 {
+ next := node.childs[index(prefix)]
+ if next == nil {
+ return false
+ }
+ pflen := commonPrefix(prefix, next.str)
+ if pflen != len(next.str) && pflen != len(prefix) {
+ return false
+ }
+ prefix = prefix[pflen:]
+ node = next
+ }
+ return true
+}
diff --git a/solutions/q209/solution.go b/solutions/2/q209/solution.go
similarity index 100%
rename from solutions/q209/solution.go
rename to solutions/2/q209/solution.go
diff --git a/solutions/2/q215/solution.go b/solutions/2/q215/solution.go
new file mode 100644
index 0000000..41c54d3
--- /dev/null
+++ b/solutions/2/q215/solution.go
@@ -0,0 +1,37 @@
+package q215
+
+func findKthLargest(nums []int, k int) int {
+ // build max-heap
+ for i := 1; i < len(nums); i++ {
+ for j := i; j > 0; j = (j - 1) / 2 {
+ parent := (j - 1) / 2
+ if nums[j] > nums[parent] {
+ nums[j], nums[parent] = nums[parent], nums[j]
+ }
+ }
+ }
+
+ for range k - 1 {
+ // pop the heap
+ nums[0] = nums[len(nums)-1]
+ nums = nums[:len(nums)-1]
+
+ i := 0
+ for i*2+1 < len(nums) {
+ l, r := i*2+1, i*2+2
+ next := l
+ if r < len(nums) && nums[r] > nums[l] {
+ next = r
+ }
+ if nums[i] >= nums[next] {
+ break
+ }
+ nums[i], nums[next] = nums[next], nums[i]
+ i = next
+ }
+ }
+
+ return nums[0]
+}
+
+var _ = findKthLargest
diff --git a/solutions/2/q228/solution.go b/solutions/2/q228/solution.go
new file mode 100644
index 0000000..15e303f
--- /dev/null
+++ b/solutions/2/q228/solution.go
@@ -0,0 +1,32 @@
+package q228
+
+import (
+ "fmt"
+ "strconv"
+)
+
+func addToRanges(output []string, a, b int) []string {
+ if a == b {
+ return append(output, strconv.FormatInt(int64(a), 10))
+ }
+ return append(output, fmt.Sprintf("%d->%d", a, b))
+}
+
+func summaryRanges(nums []int) []string {
+ if len(nums) == 0 {
+ return nil
+ }
+
+ output := []string{}
+ l := 0
+ for r := 1; r < len(nums); r++ {
+ if nums[r]-nums[r-1] != 1 {
+ output = addToRanges(output, nums[l], nums[r-1])
+ l = r
+ }
+ }
+ output = addToRanges(output, nums[l], nums[len(nums)-1])
+ return output
+}
+
+var _ = summaryRanges
diff --git a/solutions/q238/solution.go b/solutions/2/q238/solution.go
similarity index 100%
rename from solutions/q238/solution.go
rename to solutions/2/q238/solution.go
diff --git a/solutions/q238/solution_test.go b/solutions/2/q238/solution_test.go
similarity index 100%
rename from solutions/q238/solution_test.go
rename to solutions/2/q238/solution_test.go
diff --git a/solutions/24/q2483/solution.go b/solutions/24/q2483/solution.go
new file mode 100644
index 0000000..2e6b54e
--- /dev/null
+++ b/solutions/24/q2483/solution.go
@@ -0,0 +1,29 @@
+package q2483
+
+func bestClosingTime(customers string) int {
+ numY := 0
+ for i := range len(customers) {
+ if customers[i] == 'Y' {
+ numY++
+ }
+ }
+ minCloseHour := 0
+ minPenalty := numY
+ penalty := numY
+ for i := range len(customers) {
+ // close at (i + 1)th hour
+ switch customers[i] {
+ case 'N':
+ penalty++
+ case 'Y':
+ penalty--
+ }
+ if penalty < minPenalty {
+ minPenalty = penalty
+ minCloseHour = i + 1
+ }
+ }
+ return minCloseHour
+}
+
+var _ = bestClosingTime
diff --git a/solutions/q380/solution.go b/solutions/3/q380/solution.go
similarity index 100%
rename from solutions/q380/solution.go
rename to solutions/3/q380/solution.go
diff --git a/solutions/3/q383/solution.go b/solutions/3/q383/solution.go
new file mode 100644
index 0000000..8e6f390
--- /dev/null
+++ b/solutions/3/q383/solution.go
@@ -0,0 +1,25 @@
+package q383
+
+func canConstruct(ransomNote string, magazine string) bool {
+ counts := make([]int, 'z'-'a'+1)
+
+ for _, c := range magazine {
+ if c < 'a' || c > 'z' {
+ continue
+ }
+ counts[int(c)-int('a')]++
+ }
+ for _, c := range ransomNote {
+ if c < 'a' || c > 'z' {
+ continue
+ }
+ offset := int(c) - int('a')
+ counts[offset]--
+ if counts[offset] < 0 {
+ return false
+ }
+ }
+ return true
+}
+
+var _ = canConstruct
diff --git a/solutions/30/q3075/solution.go b/solutions/30/q3075/solution.go
new file mode 100644
index 0000000..e319b8d
--- /dev/null
+++ b/solutions/30/q3075/solution.go
@@ -0,0 +1,14 @@
+package q3075
+
+import "slices"
+
+func maximumHappinessSum(happiness []int, k int) int64 {
+ slices.Sort(happiness)
+ var sum int64
+ for i := range k {
+ sum += max(0, int64(happiness[len(happiness)-1-i]-i))
+ }
+ return sum
+}
+
+var _ = maximumHappinessSum
diff --git a/solutions/5/q530/solution.go b/solutions/5/q530/solution.go
new file mode 100644
index 0000000..673014c
--- /dev/null
+++ b/solutions/5/q530/solution.go
@@ -0,0 +1,37 @@
+package q530
+
+import "math"
+
+type TreeNode struct {
+ Val int
+ Left *TreeNode
+ Right *TreeNode
+}
+
+func getMinimumDifference(root *TreeNode) int {
+ minDiff := math.MaxInt
+ var last *int
+
+ var check = func(num int) {
+ if last == nil {
+ last = &num
+ return
+ }
+ minDiff = min(minDiff, num-*last)
+ *last = num
+ }
+ var traverse func(node *TreeNode)
+ traverse = func(node *TreeNode) {
+ if node == nil {
+ return
+ }
+ traverse(node.Left)
+ check(node.Val)
+ traverse(node.Right)
+ }
+ traverse(root)
+
+ return minDiff
+}
+
+var _ = getMinimumDifference
diff --git a/solutions/6/q637/solution.go b/solutions/6/q637/solution.go
new file mode 100644
index 0000000..a6822d5
--- /dev/null
+++ b/solutions/6/q637/solution.go
@@ -0,0 +1,43 @@
+package q637
+
+type TreeNode struct {
+ Val int
+ Left *TreeNode
+ Right *TreeNode
+}
+
+func averageOfLevels(root *TreeNode) []float64 {
+ type qElem struct {
+ level int
+ node *TreeNode
+ }
+
+ ret := []float64{}
+ level := 0
+ n := 0 // number of nodes
+ var sum float64
+
+ queue := []qElem{{level: 0, node: root}}
+ for ; len(queue) > 0; queue = queue[1:] {
+ curr := &queue[0]
+ if curr.level == level {
+ sum += float64(curr.node.Val)
+ n++
+ } else {
+ ret = append(ret, sum/float64(n))
+ sum = float64(curr.node.Val)
+ n = 1
+ level = curr.level
+ }
+ if curr.node.Left != nil {
+ queue = append(queue, qElem{curr.level + 1, curr.node.Left})
+ }
+ if curr.node.Right != nil {
+ queue = append(queue, qElem{curr.level + 1, curr.node.Right})
+ }
+ }
+ ret = append(ret, sum/float64(n))
+ return ret
+}
+
+var _ = averageOfLevels
diff --git a/solutions/9/q909/solution.go b/solutions/9/q909/solution.go
new file mode 100644
index 0000000..bd1e397
--- /dev/null
+++ b/solutions/9/q909/solution.go
@@ -0,0 +1,50 @@
+package q909
+
+func coord(n, num int) (x, y int) {
+ num -= 1
+ row := num / n
+ y = n - row - 1
+ x = num % n
+ if row%2 == 1 {
+ x = n - 1 - x
+ }
+ return
+}
+
+func snakesAndLadders(board [][]int) int {
+ n, sqN := len(board), len(board)*len(board)
+ leastRolls := make([]int, sqN)
+ if len(leastRolls) == 1 {
+ return 0
+ }
+
+ queue := make([]int, 0, sqN)
+ queue = append(queue, 1)
+ for ; len(queue) > 0; queue = queue[1:] {
+ cur := queue[0]
+ for dist := 1; dist <= 6 && cur+dist <= sqN; dist++ {
+ next := cur + dist
+ x, y := coord(n, next)
+ if board[y][x] != -1 {
+ next = board[y][x]
+ }
+ rolls := leastRolls[cur-1] + 1
+
+ if (next > 1 && leastRolls[next-1] == 0) || rolls < leastRolls[next-1] {
+ leastRolls[next-1] = rolls
+ if next == sqN {
+ return rolls
+ }
+ queue = append(queue, next)
+ }
+ }
+ }
+
+ l := leastRolls[sqN-1]
+ if l == 0 {
+ return -1
+ }
+ return 0
+}
+
+var _ = snakesAndLadders
diff --git a/tools.go b/tools.go
new file mode 100644
index 0000000..e24a421
--- /dev/null
+++ b/tools.go
@@ -0,0 +1,6 @@
+package leetcodego
+
+import (
+ _ "github.com/emirpasic/gods/v2/utils"
+ _ "github.com/k0kubun/pp/v3"
+)