From d798d5e8c9a91c330c22875e4693fbb39093f71f Mon Sep 17 00:00:00 2001 From: kanna5 Date: Mon, 5 Jan 2026 16:48:03 +0900 Subject: [PATCH] add new solutions --- go.sum | 4 -- solutions/0/q2/solution.go | 35 ++++++++++++++ solutions/0/q72/solution.go | 36 ++++++++++++++ solutions/0/q74/solution.go | 23 +++++++++ solutions/1/q103/solution.go | 55 ++++++++++++++++++++++ solutions/1/q106/solution.go | 26 +++++++++++ solutions/1/q117/solution.go | 34 ++++++++++++++ solutions/1/q118/solution.go | 26 +++++++++++ solutions/1/q129/solution.go | 33 +++++++++++++ solutions/1/q148/solution.go | 32 +++++++++++++ solutions/1/q173/solution.go | 65 ++++++++++++++++++++++++++ solutions/2/q201/solution.go | 21 +++++++++ solutions/2/q210/solution.go | 34 ++++++++++++++ solutions/2/q289/solution.go | 41 ++++++++++++++++ solutions/29/q2943/solution.go | 27 +++++++++++ solutions/3/q373/solution.go | 46 ++++++++++++++++++ solutions/34/q3453/solution.go | 41 ++++++++++++++++ solutions/34/q3454/solution.go | 85 ++++++++++++++++++++++++++++++++++ solutions/4/q435/solution.go | 1 + 19 files changed, 661 insertions(+), 4 deletions(-) create mode 100644 solutions/0/q2/solution.go create mode 100644 solutions/0/q72/solution.go create mode 100644 solutions/0/q74/solution.go create mode 100644 solutions/1/q103/solution.go create mode 100644 solutions/1/q106/solution.go create mode 100644 solutions/1/q117/solution.go create mode 100644 solutions/1/q118/solution.go create mode 100644 solutions/1/q129/solution.go create mode 100644 solutions/1/q148/solution.go create mode 100644 solutions/1/q173/solution.go create mode 100644 solutions/2/q201/solution.go create mode 100644 solutions/2/q210/solution.go create mode 100644 solutions/2/q289/solution.go create mode 100644 solutions/29/q2943/solution.go create mode 100644 solutions/3/q373/solution.go create mode 100644 solutions/34/q3453/solution.go create mode 100644 solutions/34/q3454/solution.go create mode 100644 solutions/4/q435/solution.go diff --git a/go.sum b/go.sum index 3151c8d..3130a0b 100644 --- a/go.sum +++ b/go.sum @@ -7,11 +7,7 @@ github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stg 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/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= -golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= diff --git a/solutions/0/q2/solution.go b/solutions/0/q2/solution.go new file mode 100644 index 0000000..581cb7f --- /dev/null +++ b/solutions/0/q2/solution.go @@ -0,0 +1,35 @@ +package q2 + +type ListNode struct { + Val int + Next *ListNode +} + +func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode { + retRoot := &ListNode{} + + p := retRoot + carry := 0 + for l1 != nil || l2 != nil { + val := carry + if l1 != nil { + val += l1.Val + l1 = l1.Next + } + if l2 != nil { + val += l2.Val + l2 = l2.Next + } + + carry, val = val/10, val%10 + node := &ListNode{Val: val} + p.Next = node + p = node + } + if carry > 0 { + p.Next = &ListNode{Val: carry} + } + return retRoot.Next +} + +var _ = addTwoNumbers diff --git a/solutions/0/q72/solution.go b/solutions/0/q72/solution.go new file mode 100644 index 0000000..5c4fb4e --- /dev/null +++ b/solutions/0/q72/solution.go @@ -0,0 +1,36 @@ +package q72 + +func make2d[T any](rows, cols int) [][]T { + alloc := make([]T, rows*cols) + ret := make([][]T, rows) + for i := range ret { + ret[i] = alloc[cols*i : cols*(i+1)] + } + return ret +} + +func minDistance(word1 string, word2 string) int { + minDists := make2d[int](len(word1)+1, len(word2)+1) + + for i1 := range len(word1) { + minDists[i1+1][0] = i1 + 1 + } + for i2 := range len(word2) { + minDists[0][i2+1] = i2 + 1 + } + + for i1 := 1; i1 <= len(word1); i1++ { + for i2 := 1; i2 <= len(word2); i2++ { + if word1[i1-1] == word2[i2-1] { + minDists[i1][i2] = minDists[i1-1][i2-1] + } else { + minDists[i1][i2] = min( + minDists[i1-1][i2], minDists[i1][i2-1], minDists[i1-1][i2-1], + ) + 1 + } + } + } + return minDists[len(word1)][len(word2)] +} + +var _ = minDistance diff --git a/solutions/0/q74/solution.go b/solutions/0/q74/solution.go new file mode 100644 index 0000000..4543215 --- /dev/null +++ b/solutions/0/q74/solution.go @@ -0,0 +1,23 @@ +package q74 + +func searchMatrix(matrix [][]int, target int) bool { + w, h := len(matrix[0]), len(matrix) + idx := func(i int) (int, int) { return i / w, i % w } + + l, r := 0, w*h + for l < r { + m := (l + r) / 2 + row, col := idx(m) + switch { + case matrix[row][col] == target: + return true + case matrix[row][col] < target: + l = m + 1 + default: + r = m + } + } + return false +} + +var _ = searchMatrix diff --git a/solutions/1/q103/solution.go b/solutions/1/q103/solution.go new file mode 100644 index 0000000..d6fb18a --- /dev/null +++ b/solutions/1/q103/solution.go @@ -0,0 +1,55 @@ +package q103 + +import "slices" + +type TreeNode struct { + Val int + Left *TreeNode + Right *TreeNode +} + +func zigzagLevelOrder(root *TreeNode) [][]int { + ret := [][]int{} + if root == nil { + return ret + } + + dpth := 1 + buf := make([]int, 512) + row := buf[:0] + + type qElem struct { + depth int + node *TreeNode + } + queue := make([]qElem, 0, 256) + queue = append(queue, qElem{depth: 1, node: root}) + for ; len(queue) > 0; queue = queue[1:] { + c := queue[0] + if c.depth > dpth { + if dpth%2 == 0 { + slices.Reverse(row) + } + ret = append(ret, make([]int, len(row))) + copy(ret[len(ret)-1], row) + + dpth = c.depth + row = buf[:0] + } + + row = append(row, c.node.Val) + if c.node.Left != nil { + queue = append(queue, qElem{depth: c.depth + 1, node: c.node.Left}) + } + if c.node.Right != nil { + queue = append(queue, qElem{depth: c.depth + 1, node: c.node.Right}) + } + } + if dpth%2 == 0 { + slices.Reverse(row) + } + ret = append(ret, row) + return ret +} + +var _ = zigzagLevelOrder diff --git a/solutions/1/q106/solution.go b/solutions/1/q106/solution.go new file mode 100644 index 0000000..91f126d --- /dev/null +++ b/solutions/1/q106/solution.go @@ -0,0 +1,26 @@ +package q106 + +import "slices" + +type TreeNode struct { + Val int + Left *TreeNode + Right *TreeNode +} + +func buildTree(inorder []int, postorder []int) *TreeNode { + if len(inorder) == 0 { + return nil + } + + val := postorder[len(postorder)-1] + pos := slices.Index(inorder, val) + + return &TreeNode{ + Val: val, + Left: buildTree(inorder[0:pos], postorder[:pos]), + Right: buildTree(inorder[pos+1:], postorder[pos:len(postorder)-1]), + } +} + +var _ = buildTree diff --git a/solutions/1/q117/solution.go b/solutions/1/q117/solution.go new file mode 100644 index 0000000..1c6ba30 --- /dev/null +++ b/solutions/1/q117/solution.go @@ -0,0 +1,34 @@ +package q117 + +type Node struct { + Val int + Left *Node + Right *Node + Next *Node +} + +func walk(node *Node, depth int, depths *[]*Node) { + if node == nil { + return + } + + if depth > len(*depths) { + *depths = append(*depths, nil) + } + if (*depths)[depth-1] != nil { + (*depths)[depth-1].Next = node + } + (*depths)[depth-1] = node + + walk(node.Left, depth+1, depths) + walk(node.Right, depth+1, depths) +} + +func connect(root *Node) *Node { + depths := []*Node{} + walk(root, 1, &depths) + + return root +} + +var _ = connect diff --git a/solutions/1/q118/solution.go b/solutions/1/q118/solution.go new file mode 100644 index 0000000..a27e6fa --- /dev/null +++ b/solutions/1/q118/solution.go @@ -0,0 +1,26 @@ +package q118 + +func generate(numRows int) [][]int { + buf := make([]int, numRows*(1+numRows)/2) + p := 0 + take := func(n int) []int { + ret := buf[p : p+n] + p = p + n + return ret + } + + ret := make([][]int, 0, numRows) + + for i := 1; i <= numRows; i++ { + row := take(i) + row[0] = 1 + row[len(row)-1] = 1 + for j := 1; j < len(row)-1; j++ { + row[j] = ret[i-2][j-1] + ret[i-2][j] + } + ret = append(ret, row) + } + return ret +} + +var _ = generate diff --git a/solutions/1/q129/solution.go b/solutions/1/q129/solution.go new file mode 100644 index 0000000..eb0bc8d --- /dev/null +++ b/solutions/1/q129/solution.go @@ -0,0 +1,33 @@ +package q129 + +type TreeNode struct { + Val int + Left *TreeNode + Right *TreeNode +} + +func sumNums(node *TreeNode, prefix int) int { + prefix = prefix*10 + node.Val + + if node.Left == nil && node.Right == nil { + return prefix + } + + sum := 0 + if node.Left != nil { + sum += sumNums(node.Left, prefix) + } + if node.Right != nil { + sum += sumNums(node.Right, prefix) + } + return sum +} + +func sumNumbers(root *TreeNode) int { + if root == nil { + return 0 + } + return sumNums(root, 0) +} + +var _ = sumNumbers diff --git a/solutions/1/q148/solution.go b/solutions/1/q148/solution.go new file mode 100644 index 0000000..ea488d4 --- /dev/null +++ b/solutions/1/q148/solution.go @@ -0,0 +1,32 @@ +package q148 + +import "slices" + +type ListNode struct { + Val int + Next *ListNode +} + +func sortList(head *ListNode) *ListNode { + if head == nil { + return nil + } + + arr := []*ListNode{} + for head != nil { + arr = append(arr, head) + head = head.Next + } + + slices.SortFunc(arr, func(a, b *ListNode) int { return a.Val - b.Val }) + for i := range arr { + if i == len(arr)-1 { + arr[i].Next = nil + } else { + arr[i].Next = arr[i+1] + } + } + return arr[0] +} + +var _ = sortList diff --git a/solutions/1/q173/solution.go b/solutions/1/q173/solution.go new file mode 100644 index 0000000..9c7b1c6 --- /dev/null +++ b/solutions/1/q173/solution.go @@ -0,0 +1,65 @@ +package q173 + +type TreeNode struct { + Val int + Left *TreeNode + Right *TreeNode +} + +type stackElem struct { + state uint8 // 0, 1, 2, 3 + node *TreeNode +} + +type BSTIterator struct { + stack []stackElem + next *TreeNode +} + +func Constructor(root *TreeNode) BSTIterator { + return BSTIterator{stack: []stackElem{{node: root}}} +} + +func (it *BSTIterator) Next() int { + it.findNext() + ret := it.next.Val + it.next = nil + return ret +} + +func (it *BSTIterator) HasNext() bool { + it.findNext() + return it.next != nil +} + +func (it *BSTIterator) findNext() { + for it.next == nil && len(it.stack) > 0 { + c := &it.stack[len(it.stack)-1] + c.state++ + + switch c.state - 1 { + case 0: // init + if c.node.Left != nil { + it.stack = append(it.stack, stackElem{node: c.node.Left}) + } + + case 1: // left processed + it.next = c.node + + case 2: // middle processed + if c.node.Right != nil { + it.stack = append(it.stack, stackElem{node: c.node.Right}) + } + + case 3: // right processed + it.stack = it.stack[:len(it.stack)-1] + } + } +} + +/** + * Your BSTIterator object will be instantiated and called as such: + * obj := Constructor(root); + * param_1 := obj.Next(); + * param_2 := obj.HasNext(); + */ diff --git a/solutions/2/q201/solution.go b/solutions/2/q201/solution.go new file mode 100644 index 0000000..9324e60 --- /dev/null +++ b/solutions/2/q201/solution.go @@ -0,0 +1,21 @@ +package q201 + +func rangeBitwiseAnd(left int, right int) int { + ret := left & right + for i := ret + 1; i < right; { + ret &= i + if ret == 0 { + return 0 + } + + // Find first non-zero bit + t := 1 + for i|t != i { + t <<= 1 + } + i += t + } + return ret +} + +var _ = rangeBitwiseAnd diff --git a/solutions/2/q210/solution.go b/solutions/2/q210/solution.go new file mode 100644 index 0000000..2d745cd --- /dev/null +++ b/solutions/2/q210/solution.go @@ -0,0 +1,34 @@ +package q210 + +func findOrder(numCourses int, prerequisites [][]int) []int { + ndeps := make([]int, numCourses) + revDeps := make([][]int, numCourses) + ret := make([]int, 0, numCourses) + + for i := range prerequisites { + c, dep := prerequisites[i][0], prerequisites[i][1] + ndeps[c]++ + revDeps[dep] = append(revDeps[dep], c) + } + + for i := range ndeps { + if ndeps[i] == 0 { + ret = append(ret, i) + } + } + for i := 0; i < len(ret); i++ { + for _, c := range revDeps[ret[i]] { + ndeps[c]-- + if ndeps[c] == 0 { + ret = append(ret, c) + } + } + } + + if len(ret) != numCourses { + return nil + } + return ret +} + +var _ = findOrder diff --git a/solutions/2/q289/solution.go b/solutions/2/q289/solution.go new file mode 100644 index 0000000..e8d0ed9 --- /dev/null +++ b/solutions/2/q289/solution.go @@ -0,0 +1,41 @@ +package q289 + +func countLiveNeighbors(board [][]int, row, col int) int { + cnt := 0 + for r := row - 1; r <= row+1; r++ { + for c := col - 1; c <= col+1; c++ { + if r == row && c == col || r < 0 || c < 0 || r >= len(board) || c >= len(board[0]) { + continue + } + cnt += board[r][c] & 1 + } + } + return cnt +} + +func gameOfLife(board [][]int) { + for r := range board { + for c := range board[r] { + neighbors := countLiveNeighbors(board, r, c) + if board[r][c]&1 == 1 { + switch { + case neighbors < 2 || neighbors > 3: + // die + default: + board[r][c] |= 2 // survive + } + } else if neighbors == 3 { + board[r][c] |= 2 // birth + } + } + } + + // Next generation + for r := range board { + for c := range board[r] { + board[r][c] >>= 1 + } + } +} + +var _ = gameOfLife diff --git a/solutions/29/q2943/solution.go b/solutions/29/q2943/solution.go new file mode 100644 index 0000000..c2dbfba --- /dev/null +++ b/solutions/29/q2943/solution.go @@ -0,0 +1,27 @@ +package q2943 + +import "slices" + +func longestSeq(arr []int) int { + max_ := 1 + len_ := 1 + for i := 1; i < len(arr); i++ { + if arr[i] == arr[i-1]+1 { + len_++ + } else { + len_ = 1 + } + max_ = max(len_, max_) + } + return max_ +} + +func maximizeSquareHoleArea(n, m int, hBars, vBars []int) int { + slices.Sort(hBars) + slices.Sort(vBars) + + edge := min(longestSeq(hBars), longestSeq(vBars)) + 1 + return edge * edge +} + +var _ = maximizeSquareHoleArea diff --git a/solutions/3/q373/solution.go b/solutions/3/q373/solution.go new file mode 100644 index 0000000..b07158c --- /dev/null +++ b/solutions/3/q373/solution.go @@ -0,0 +1,46 @@ +package q373 + +import "container/heap" + +type MHeap [][]int + +func (m *MHeap) Len() int { return len(*m) } + +func (m *MHeap) Less(i int, j int) bool { + return (*m)[i][0]+(*m)[i][1] > (*m)[j][0]+(*m)[j][1] +} + +func (m *MHeap) Pop() any { + ret := (*m)[len(*m)-1] + *m = (*m)[:len(*m)-1] + return ret +} + +func (m *MHeap) Push(x any) { + elem, _ := x.([]int) + *m = append(*m, elem) +} + +func (m *MHeap) Swap(i int, j int) { (*m)[i], (*m)[j] = (*m)[j], (*m)[i] } + +func kSmallestPairs(nums1 []int, nums2 []int, k int) [][]int { + h := make(MHeap, 0, k) + for i := range min(k, len(nums1)) { + for j := range min(k, len(nums2)) { + if h.Len() < k { + heap.Push(&h, []int{nums1[i], nums2[j]}) + continue + } + + if nums1[i]+nums2[j] >= h[0][0]+h[0][1] { + break + } + h[0][0], h[0][1] = nums1[i], nums2[j] + heap.Fix(&h, 0) + } + } + + return h +} + +var _ = kSmallestPairs diff --git a/solutions/34/q3453/solution.go b/solutions/34/q3453/solution.go new file mode 100644 index 0000000..75c5320 --- /dev/null +++ b/solutions/34/q3453/solution.go @@ -0,0 +1,41 @@ +package q3453 + +import ( + "math" + "slices" +) + +func separateSquares(squares [][]int) float64 { + slices.SortFunc(squares, func(a, b []int) int { return a[1] - b[1] }) + var totalArea float64 + var maxY int + for i := range squares { + totalArea += math.Pow(float64(squares[i][2]), 2) + maxY = max(maxY, squares[i][1]+squares[i][2]) + } + + target := totalArea / 2 + + // Binary search + var l, r float64 = 0, float64(maxY) + for range 64 { + m := (l + r) / 2 + + var area float64 + for i := range squares { + y, l := float64(squares[i][1]), float64(squares[i][2]) + if y >= m { + break + } + area += l * min(l, m-y) + } + if area < target { + l = m + } else { + r = m + } + } + return l +} + +var _ = separateSquares diff --git a/solutions/34/q3454/solution.go b/solutions/34/q3454/solution.go new file mode 100644 index 0000000..a9c67d5 --- /dev/null +++ b/solutions/34/q3454/solution.go @@ -0,0 +1,85 @@ +package q3454 + +import ( + "math" + "slices" +) + +type void struct{} + +func calcLengthAtY(squares [][]int) [][2]int { + vertIdx := make([][2]int, len(squares)*2) + for i := range squares { + vertIdx[i*2] = [2]int{squares[i][1], i} + vertIdx[i*2+1] = [2]int{squares[i][1] + squares[i][2], i} + } + slices.SortFunc(vertIdx, func(a, b [2]int) int { return a[0] - b[0] }) + + curSq := map[int]void{} + curLenBuf := make([][2]int, len(squares)) + + calcLen := func() int { + curLen := 0 + curLenBuf = curLenBuf[:0] + for i := range curSq { + l := squares[i][0] + r := l + squares[i][2] + curLenBuf = append(curLenBuf, [2]int{l, r}) + } + slices.SortFunc(curLenBuf, func(a, b [2]int) int { return a[0] - b[0] }) + r := math.MinInt + for i := range curLenBuf { + if curLenBuf[i][0] < r { + curLen += max(0, curLenBuf[i][1]-r) + } else { + curLen += curLenBuf[i][1] - curLenBuf[i][0] + } + r = max(r, curLenBuf[i][1]) + } + return curLen + } + + ret := make([][2]int, 0, len(squares)*2) + for i := 0; i < len(vertIdx); { + curY := vertIdx[i][0] + for ; i < len(vertIdx) && vertIdx[i][0] == curY; i++ { + sq := vertIdx[i][1] + if _, ok := curSq[sq]; ok { + delete(curSq, sq) + } else { + curSq[sq] = void{} + } + } + + ret = append(ret, [2]int{curY, calcLen()}) + } + return ret +} + +func separateSquares(squares [][]int) float64 { + lenAtY := calcLengthAtY(squares) + + totalArea := 0 + for i := 0; i < len(lenAtY)-1; i++ { + totalArea += lenAtY[i][1] * (lenAtY[i+1][0] - lenAtY[i][0]) + } + + var area int + for i := 0; i < len(lenAtY)-1; i++ { + y, nextY := lenAtY[i][0], lenAtY[i+1][0] + l := lenAtY[i][1] + + areaT := (nextY-y)*l + area + switch { + case areaT*2 == totalArea: + return float64(nextY) + case areaT*2 > totalArea: + needed := float64(totalArea-area*2) / 2 + return float64(y) + needed/float64(l) + } + area = areaT + } + return -1 +} + +var _ = separateSquares diff --git a/solutions/4/q435/solution.go b/solutions/4/q435/solution.go new file mode 100644 index 0000000..737290c --- /dev/null +++ b/solutions/4/q435/solution.go @@ -0,0 +1 @@ +package q435