From 886b5e0a8e9bab348da3dff0fb21befc73c8e12e Mon Sep 17 00:00:00 2001 From: kanna5 Date: Mon, 5 Jan 2026 16:48:03 +0900 Subject: [PATCH] add new solutions --- solutions/0/q12/solution.go | 39 ++++++++++++++++++++ solutions/0/q19/solution.go | 26 ++++++++++++++ solutions/0/q3/solution.go | 20 +++++++++++ solutions/0/q33/solution.go | 46 ++++++++++++++++++++++++ solutions/0/q34/solution.go | 26 ++++++++++++++ solutions/0/q39/solution.go | 30 ++++++++++++++++ solutions/0/q46/solution.go | 34 ++++++++++++++++++ solutions/0/q48/solution.go | 21 +++++++++++ solutions/0/q49/solution.go | 22 ++++++++++++ solutions/0/q54/solution.go | 40 +++++++++++++++++++++ solutions/0/q57/solution.go | 30 ++++++++++++++++ solutions/0/q6/solution.go | 27 ++++++++++++++ solutions/0/q61/solution.go | 35 ++++++++++++++++++ solutions/0/q64/solution.go | 21 +++++++++++ solutions/0/q71/solution.go | 32 +++++++++++++++++ solutions/0/q73/solution.go | 24 +++++++++++++ solutions/0/q77/solution.go | 51 ++++++++++++++++++++++++++ solutions/0/q79/solution.go | 61 +++++++++++++++++++++++++++++++ solutions/0/q86/solution.go | 30 ++++++++++++++++ solutions/0/q92/solution.go | 25 +++++++++++++ solutions/0/q98/solution.go | 39 ++++++++++++++++++++ solutions/1/q128/solution.go | 27 ++++++++++++++ solutions/1/q130/solution.go | 37 +++++++++++++++++++ solutions/1/q138/solution.go | 34 ++++++++++++++++++ solutions/1/q139/solution.go | 28 +++++++++++++++ solutions/1/q153/solution.go | 18 ++++++++++ solutions/1/q162/solution.go | 24 +++++++++++++ solutions/2/q211/solution.go | 63 ++++++++++++++++++++++++++++++++ solutions/2/q236/solution.go | 31 ++++++++++++++++ solutions/29/q2975/solution.go | 50 ++++++++++++++++++++++++++ solutions/3/q300/solution.go | 21 +++++++++++ solutions/30/q3047/solution.go | 42 ++++++++++++++++++++++ solutions/4/q427/solution.go | 44 +++++++++++++++++++++++ solutions/9/q986/solution.go | 66 ++++++++++++++++++++++++++++++++++ 34 files changed, 1164 insertions(+) create mode 100644 solutions/0/q12/solution.go create mode 100644 solutions/0/q19/solution.go create mode 100644 solutions/0/q3/solution.go create mode 100644 solutions/0/q33/solution.go create mode 100644 solutions/0/q34/solution.go create mode 100644 solutions/0/q39/solution.go create mode 100644 solutions/0/q46/solution.go create mode 100644 solutions/0/q48/solution.go create mode 100644 solutions/0/q49/solution.go create mode 100644 solutions/0/q54/solution.go create mode 100644 solutions/0/q57/solution.go create mode 100644 solutions/0/q6/solution.go create mode 100644 solutions/0/q61/solution.go create mode 100644 solutions/0/q64/solution.go create mode 100644 solutions/0/q71/solution.go create mode 100644 solutions/0/q73/solution.go create mode 100644 solutions/0/q77/solution.go create mode 100644 solutions/0/q79/solution.go create mode 100644 solutions/0/q86/solution.go create mode 100644 solutions/0/q92/solution.go create mode 100644 solutions/0/q98/solution.go create mode 100644 solutions/1/q128/solution.go create mode 100644 solutions/1/q130/solution.go create mode 100644 solutions/1/q138/solution.go create mode 100644 solutions/1/q139/solution.go create mode 100644 solutions/1/q153/solution.go create mode 100644 solutions/1/q162/solution.go create mode 100644 solutions/2/q211/solution.go create mode 100644 solutions/2/q236/solution.go create mode 100644 solutions/29/q2975/solution.go create mode 100644 solutions/3/q300/solution.go create mode 100644 solutions/30/q3047/solution.go create mode 100644 solutions/4/q427/solution.go create mode 100644 solutions/9/q986/solution.go diff --git a/solutions/0/q12/solution.go b/solutions/0/q12/solution.go new file mode 100644 index 0000000..0c8ff69 --- /dev/null +++ b/solutions/0/q12/solution.go @@ -0,0 +1,39 @@ +package q12 + +import "strings" + +var mapping = []struct { + string + int +}{ + {"I", 1}, + {"IV", 4}, + {"V", 5}, + {"IX", 9}, + {"X", 10}, + {"XL", 40}, + {"L", 50}, + {"XC", 90}, + {"C", 100}, + {"CD", 400}, + {"D", 500}, + {"CM", 900}, + {"M", 1000}, +} + +func intToRoman(num int) string { + b := &strings.Builder{} + + for i := len(mapping) - 1; i >= 0; i-- { + for num >= mapping[i].int { + num -= mapping[i].int + b.WriteString(mapping[i].string) + } + if num == 0 { + break + } + } + return b.String() +} + +var _ = intToRoman diff --git a/solutions/0/q19/solution.go b/solutions/0/q19/solution.go new file mode 100644 index 0000000..06a6f9a --- /dev/null +++ b/solutions/0/q19/solution.go @@ -0,0 +1,26 @@ +package q19 + +type ListNode struct { + Val int + Next *ListNode +} + +func removeNthFromEnd(head *ListNode, n int) *ListNode { + stub := &ListNode{Next: head} + + probe := stub + for range n { + probe = probe.Next + } + prev := stub + + for probe.Next != nil { + probe = probe.Next + prev = prev.Next + } + prev.Next = prev.Next.Next + + return stub.Next +} + +var _ = removeNthFromEnd diff --git a/solutions/0/q3/solution.go b/solutions/0/q3/solution.go new file mode 100644 index 0000000..52466e0 --- /dev/null +++ b/solutions/0/q3/solution.go @@ -0,0 +1,20 @@ +package q3 + +func lengthOfLongestSubstring(s string) int { + seen := make([]bool, 256) + maxLen := 0 + + l := 0 + for r := range len(s) { + c := s[r] + for seen[c] { + seen[s[l]] = false + l++ + } + seen[c] = true + maxLen = max(maxLen, r-l+1) + } + return maxLen +} + +var _ = lengthOfLongestSubstring diff --git a/solutions/0/q33/solution.go b/solutions/0/q33/solution.go new file mode 100644 index 0000000..2ab6a35 --- /dev/null +++ b/solutions/0/q33/solution.go @@ -0,0 +1,46 @@ +package q33 + +func findK(nums []int) int { + if len(nums) < 2 || nums[0] < nums[len(nums)-1] { + return 0 + } + + l, r := 0, len(nums) + for l < r && nums[l] > nums[r-1] { + m := (l + r) / 2 + if nums[m] > nums[r-1] { + l = m + 1 + } else { + r = m + 1 + l++ + } + } + return len(nums) - l +} + +func translate(n, k, i int) int { + if i < k { + return n + i - k + } + return i - k +} + +func search(nums []int, target int) int { + k := findK(nums) + + l, r := 0, len(nums) + for l < r { + m := (l + r) / 2 + mt := translate(len(nums), k, m) + if nums[mt] == target { + return mt + } else if nums[mt] > target { + r = m + } else { + l = m + 1 + } + } + return -1 +} + +var _ = search diff --git a/solutions/0/q34/solution.go b/solutions/0/q34/solution.go new file mode 100644 index 0000000..4f00f27 --- /dev/null +++ b/solutions/0/q34/solution.go @@ -0,0 +1,26 @@ +package q34 + +func find(nums []int, target int) int { + l, r := 0, len(nums) + for l < r { + m := (l + r) / 2 + switch { + case nums[m] < target: + l = m + 1 + default: + r = m + } + } + return l +} + +func searchRange(nums []int, target int) []int { + pos := find(nums, target) + if pos < 0 || pos >= len(nums) || nums[pos] != target { + return []int{-1, -1} + } + pos2 := find(nums[pos:], target+1) + return []int{pos, pos + pos2 - 1} +} + +var _ = searchRange diff --git a/solutions/0/q39/solution.go b/solutions/0/q39/solution.go new file mode 100644 index 0000000..ece03b3 --- /dev/null +++ b/solutions/0/q39/solution.go @@ -0,0 +1,30 @@ +package q39 + +import "slices" + +func mkCombs(candidates []int, target int, buf []int, ret [][]int) [][]int { + if target == 0 { + cp := make([]int, len(buf)) + copy(cp, buf) + return append(ret, buf) + } + if len(candidates) == 0 || candidates[0] > target { + return ret + } + for i := 0; candidates[0]*i <= target; i++ { + ret = mkCombs(candidates[1:], target-i*candidates[0], buf, ret) + buf = append(buf, candidates[0]) + } + return ret +} + +func combinationSum(candidates []int, target int) [][]int { + slices.Sort(candidates) + + ret := make([][]int, 0, 150) + buf := make([]int, target/candidates[0]+1) + + return mkCombs(candidates, target, buf[:0], ret) +} + +var _ = combinationSum diff --git a/solutions/0/q46/solution.go b/solutions/0/q46/solution.go new file mode 100644 index 0000000..7500ab4 --- /dev/null +++ b/solutions/0/q46/solution.go @@ -0,0 +1,34 @@ +package q46 + +func recurse(nums []int, offset int, buf []int, seen []bool, ret [][]int) [][]int { + if offset == len(nums) { + a := make([]int, len(buf)) + copy(a, buf) + return append(ret, a) + } + + for i := range nums { + if seen[i] { + continue + } + seen[i] = true + buf[offset] = nums[i] + ret = recurse(nums, offset+1, buf, seen, ret) + seen[i] = false + } + return ret +} + +func permute(nums []int) [][]int { + totalLen := 1 + for i := range len(nums) { + totalLen *= i + 1 + } + ret := make([][]int, 0, totalLen) + buf := make([]int, len(nums)) + seen := make([]bool, len(nums)) + + return recurse(nums, 0, buf, seen, ret) +} + +var _ = permute diff --git a/solutions/0/q48/solution.go b/solutions/0/q48/solution.go new file mode 100644 index 0000000..31b5609 --- /dev/null +++ b/solutions/0/q48/solution.go @@ -0,0 +1,21 @@ +package q48 + +func rotateCell(matrix [][]int, x, y int) { + t := matrix[y][x] + for range 4 { + nextX, nextY := len(matrix)-1-y, x + matrix[nextY][nextX], t = t, matrix[nextY][nextX] + x, y = nextX, nextY + } +} + +func rotate(matrix [][]int) { + w := len(matrix) + for y := range w / 2 { + for x := y; x < w-y-1; x++ { + rotateCell(matrix, x, y) + } + } +} + +var _ = rotate diff --git a/solutions/0/q49/solution.go b/solutions/0/q49/solution.go new file mode 100644 index 0000000..8b55209 --- /dev/null +++ b/solutions/0/q49/solution.go @@ -0,0 +1,22 @@ +package q49 + +import "slices" + +func groupAnagrams(strs []string) [][]string { + groups := map[string][]string{} + + for i := range strs { + byt := []byte(strs[i]) + slices.Sort(byt) + sorted := string(byt) + groups[sorted] = append(groups[sorted], strs[i]) + } + + ret := make([][]string, 0, len(groups)) + for _, g := range groups { + ret = append(ret, g) + } + return ret +} + +var _ = groupAnagrams diff --git a/solutions/0/q54/solution.go b/solutions/0/q54/solution.go new file mode 100644 index 0000000..25b2570 --- /dev/null +++ b/solutions/0/q54/solution.go @@ -0,0 +1,40 @@ +package q54 + +import "math" + +var dirs = [4][2]int{ + {1, 0}, // right + {0, 1}, // down + {-1, 0}, // left + {0, -1}, // up +} + +const VISITED = math.MinInt + +func spiralOrder(matrix [][]int) []int { + w, h := len(matrix[0]), len(matrix) + cnt := w * h + ret := make([]int, cnt) + + x, y := 0, 0 + dir := 0 + vect := dirs[dir] + + for i := range cnt { + ret[i] = matrix[y][x] + matrix[y][x] = VISITED + + // Can move? + nextX, nextY := x+vect[0], y+vect[1] + if nextX < 0 || nextY < 0 || nextX == w || nextY == h || matrix[nextY][nextX] == VISITED { + dir = (dir + 1) % 4 + vect = dirs[dir] + nextX, nextY = x+vect[0], y+vect[1] + } + x, y = nextX, nextY + } + + return ret +} + +var _ = spiralOrder diff --git a/solutions/0/q57/solution.go b/solutions/0/q57/solution.go new file mode 100644 index 0000000..62fea24 --- /dev/null +++ b/solutions/0/q57/solution.go @@ -0,0 +1,30 @@ +package q57 + +func insert(intervals [][]int, newInterval []int) [][]int { + ret := make([][]int, 0, len(intervals)+1) + + i := 0 + for ; i < len(intervals) && intervals[i][0] <= newInterval[0]; i++ { + ret = append(ret, intervals[i]) + } + + if len(ret) > 0 && ret[len(ret)-1][1] >= newInterval[0] { + ret[len(ret)-1][1] = max(ret[len(ret)-1][1], newInterval[1]) + } else { + ret = append(ret, newInterval) + } + + for ; i < len(intervals); i++ { + last := ret[len(ret)-1] + next := intervals[i] + if last[1] >= next[0] { + last[1] = max(last[1], next[1]) + } else { + ret = append(ret, next) + } + } + + return ret +} + +var _ = insert diff --git a/solutions/0/q6/solution.go b/solutions/0/q6/solution.go new file mode 100644 index 0000000..31b15fd --- /dev/null +++ b/solutions/0/q6/solution.go @@ -0,0 +1,27 @@ +package q6 + +import "strings" + +func convert(s string, numRows int) string { + loopLen := numRows + max(0, numRows-2) + rows := make([][]byte, numRows) + for i := range numRows { + rows[i] = make([]byte, 0, (len(s)/loopLen+1)*2) + } + + for i := range len(s) { + row := i % loopLen + if row >= numRows { + row = numRows - row%numRows - 2 + } + rows[row] = append(rows[row], s[i]) + } + + b := strings.Builder{} + for i := range rows { + _, _ = b.Write(rows[i]) + } + return b.String() +} + +var _ = convert diff --git a/solutions/0/q61/solution.go b/solutions/0/q61/solution.go new file mode 100644 index 0000000..7fe1cb1 --- /dev/null +++ b/solutions/0/q61/solution.go @@ -0,0 +1,35 @@ +package q61 + +type ListNode struct { + Val int + Next *ListNode +} + +func rotateRight(head *ListNode, k int) *ListNode { + if head == nil { + return nil + } + n := 1 + p := head + for p.Next != nil { + p = p.Next + n++ + } + tail := p + + k %= n + if k == 0 { + return head + } + + tail.Next = head + p = head + for range n - k - 1 { + p = p.Next + } + newHead := p.Next + p.Next = nil + return newHead +} + +var _ = rotateRight diff --git a/solutions/0/q64/solution.go b/solutions/0/q64/solution.go new file mode 100644 index 0000000..d8bb586 --- /dev/null +++ b/solutions/0/q64/solution.go @@ -0,0 +1,21 @@ +package q64 + +func minPathSum(grid [][]int) int { + w, h := len(grid[0]), len(grid) + + for y := 1; y < h; y++ { + grid[y][0] += grid[y-1][0] + } + for x := 1; x < w; x++ { + grid[0][x] += grid[0][x-1] + } + + for y := 1; y < h; y++ { + for x := 1; x < w; x++ { + grid[y][x] += min(grid[y-1][x], grid[y][x-1]) + } + } + return grid[h-1][w-1] +} + +var _ = minPathSum diff --git a/solutions/0/q71/solution.go b/solutions/0/q71/solution.go new file mode 100644 index 0000000..bf2668b --- /dev/null +++ b/solutions/0/q71/solution.go @@ -0,0 +1,32 @@ +package q71 + +import "strings" + +func simplifyPath(path string) string { + b := strings.Builder{} + fields := strings.FieldsFunc(path, func(r rune) bool { return r == '/' }) + + p := 0 + for i := range fields { + switch fields[i] { + case ".": + continue + case "..": + p = max(p-1, 0) + default: + fields[p] = fields[i] + p++ + } + } + for i := range p { + b.WriteByte('/') + b.WriteString(fields[i]) + } + + if p == 0 { + return "/" + } + return b.String() +} + +var _ = simplifyPath diff --git a/solutions/0/q73/solution.go b/solutions/0/q73/solution.go new file mode 100644 index 0000000..1b373ff --- /dev/null +++ b/solutions/0/q73/solution.go @@ -0,0 +1,24 @@ +package q73 + +func setZeroes(matrix [][]int) { + zRows := make([]bool, len(matrix)) + zCols := make([]bool, len(matrix[0])) + for r := range matrix { + for c := range matrix[0] { + if matrix[r][c] == 0 { + zRows[r] = true + zCols[c] = true + } + } + } + + for r := range matrix { + for c := range matrix[0] { + if zRows[r] || zCols[c] { + matrix[r][c] = 0 + } + } + } +} + +var _ = setZeroes diff --git a/solutions/0/q77/solution.go b/solutions/0/q77/solution.go new file mode 100644 index 0000000..9e987b6 --- /dev/null +++ b/solutions/0/q77/solution.go @@ -0,0 +1,51 @@ +package q77 + +var ( + allocBuf []int + allocP int +) + +func alloc(sz int) []int { + if allocBuf == nil || allocP+sz > 8192 { + allocP = 0 + allocBuf = make([]int, 8192) + } + ret := allocBuf[allocP : allocP+sz] + allocP += sz + return ret +} + +func combine(n int, k int) [][]int { + buf := alloc(k) + for i := range buf { + buf[i] = i + 1 + } + + sz := 1 + for i := 1; i <= k; i++ { + sz = sz * (n - i + 1) / i + } + ret := make([][]int, 0, sz) + for { + t := alloc(k) + copy(t, buf) + ret = append(ret, t) + + if buf[0] == n-k+1 { + break + } + + buf[k-1]++ + i := k - 1 + for ; i > 0 && buf[i] > n-(k-1-i); i-- { + buf[i-1]++ + } + for i++; i < k; i++ { + buf[i] = buf[i-1] + 1 + } + } + + return ret +} + +var _ = combine diff --git a/solutions/0/q79/solution.go b/solutions/0/q79/solution.go new file mode 100644 index 0000000..437b339 --- /dev/null +++ b/solutions/0/q79/solution.go @@ -0,0 +1,61 @@ +package q79 + +func search(board [][]byte, word string, prefixLen, row, col int) bool { + if row < 0 || col < 0 || row >= len(board) || col >= len(board[0]) { + return false + } + if word[prefixLen] != board[row][col] { + return false + } + if prefixLen+1 == len(word) { + return true + } + + c := board[row][col] + board[row][col] = '#' + yes := false || + search(board, word, prefixLen+1, row, col+1) || + search(board, word, prefixLen+1, row, col-1) || + search(board, word, prefixLen+1, row+1, col) || + search(board, word, prefixLen+1, row-1, col) + + board[row][col] = c + return yes +} + +func exist(board [][]byte, word string) bool { + w, h := len(board[0]), len(board) + if len(word) > w*h { + return false + } + charFreq := make([]int, 26*2) + idx := func(b byte) byte { + if b >= 'a' { + return b - 'a' + 26 + } + return b - 'A' + } + for row := range board { + for col := range board[0] { + charFreq[idx(board[row][col])]++ + } + } + for i := range len(word) { + ii := idx(word[i]) + charFreq[ii]-- + if charFreq[ii] < 0 { + return false + } + } + + for row := range board { + for col := range board[0] { + if search(board, word, 0, row, col) { + return true + } + } + } + return false +} + +var _ = exist diff --git a/solutions/0/q86/solution.go b/solutions/0/q86/solution.go new file mode 100644 index 0000000..de9c52f --- /dev/null +++ b/solutions/0/q86/solution.go @@ -0,0 +1,30 @@ +package q86 + +type ListNode struct { + Val int + Next *ListNode +} + +func partition(head *ListNode, x int) *ListNode { + stub := &ListNode{Next: head} + before := stub + for before.Next != nil && before.Next.Val < x { + before = before.Next + } + + for p := before.Next; p != nil && p.Next != nil; { + if p.Next.Val < x { + move := p.Next + p.Next = move.Next + + move.Next = before.Next + before.Next = move + before = move + } else { + p = p.Next + } + } + return stub.Next +} + +var _ = partition diff --git a/solutions/0/q92/solution.go b/solutions/0/q92/solution.go new file mode 100644 index 0000000..edc2934 --- /dev/null +++ b/solutions/0/q92/solution.go @@ -0,0 +1,25 @@ +package q92 + +type ListNode struct { + Val int + Next *ListNode +} + +func reverseBetween(head *ListNode, left int, right int) *ListNode { + stub := &ListNode{Next: head} + before := stub + for range left - 1 { + before = before.Next + } + + curr := before.Next + for range right - left { + move := curr.Next + curr.Next = move.Next + move.Next = before.Next + before.Next = move + } + return stub.Next +} + +var _ = reverseBetween diff --git a/solutions/0/q98/solution.go b/solutions/0/q98/solution.go new file mode 100644 index 0000000..fa20161 --- /dev/null +++ b/solutions/0/q98/solution.go @@ -0,0 +1,39 @@ +package q98 + +type TreeNode struct { + Val int + Left *TreeNode + Right *TreeNode +} + +func isValid(node *TreeNode) (bool, int, int) { + if node.Left == nil && node.Right == nil { + return true, node.Val, node.Val + } + + minv, maxv := node.Val, node.Val + + if node.Left != nil { + valid, lmin, lmax := isValid(node.Left) + if !valid || lmax >= node.Val { + return false, 0, 0 + } + minv = lmin + } + if node.Right != nil { + valid, rmin, rmax := isValid(node.Right) + if !valid || rmin <= node.Val { + return false, 0, 0 + } + maxv = rmax + } + + return true, minv, maxv +} + +func isValidBST(root *TreeNode) bool { + valid, _, _ := isValid(root) + return valid +} + +var _ = isValidBST diff --git a/solutions/1/q128/solution.go b/solutions/1/q128/solution.go new file mode 100644 index 0000000..129ccb1 --- /dev/null +++ b/solutions/1/q128/solution.go @@ -0,0 +1,27 @@ +package q128 + +func longestConsecutive(nums []int) int { + set := make(map[int]struct{}, len(nums)) + for _, n := range nums { + set[n] = struct{}{} + } + + longest := 0 + for n := range set { + if _, ok := set[n-1]; ok { + continue + } + r := n + for { + if _, ok := set[r+1]; ok { + r++ + } else { + break + } + } + longest = max(longest, r-n+1) + } + return longest +} + +var _ = longestConsecutive diff --git a/solutions/1/q130/solution.go b/solutions/1/q130/solution.go new file mode 100644 index 0000000..d11467a --- /dev/null +++ b/solutions/1/q130/solution.go @@ -0,0 +1,37 @@ +package q130 + +func markI(board [][]byte, x, y int) { + w, h := len(board[0]), len(board) + if x < 0 || y < 0 || x >= w || y >= h || board[y][x] != 'O' { + return + } + board[y][x] = 'I' + markI(board, x, y+1) + markI(board, x, y-1) + markI(board, x+1, y) + markI(board, x-1, y) +} + +func solve(board [][]byte) { + for i := range len(board) { + markI(board, 0, i) + markI(board, len(board[0])-1, i) + } + for i := range len(board[0]) { + markI(board, i, 0) + markI(board, i, len(board)-1) + } + + for y := range board { + for x := range board[0] { + switch board[y][x] { + case 'O': + board[y][x] = 'X' + case 'I': + board[y][x] = 'O' + } + } + } +} + +var _ = solve diff --git a/solutions/1/q138/solution.go b/solutions/1/q138/solution.go new file mode 100644 index 0000000..ecfbda4 --- /dev/null +++ b/solutions/1/q138/solution.go @@ -0,0 +1,34 @@ +package q138 + +type Node struct { + Val int + Next *Node + Random *Node +} + +func copyRandomList(head *Node) *Node { + idx := make(map[*Node]*Node, 256) + + p := head + for p != nil { + newNode := *p // copy + idx[p] = &newNode + p = p.Next + } + + p = head + for p != nil { + newNode := idx[p] + if newNode.Next != nil { + newNode.Next = idx[newNode.Next] + } + if newNode.Random != nil { + newNode.Random = idx[newNode.Random] + } + p = p.Next + } + + return idx[head] +} + +var _ = copyRandomList diff --git a/solutions/1/q139/solution.go b/solutions/1/q139/solution.go new file mode 100644 index 0000000..0935c3b --- /dev/null +++ b/solutions/1/q139/solution.go @@ -0,0 +1,28 @@ +package q139 + +func wordBreak(s string, wordDict []string) bool { + possible := make([]bool, len(s)+1) + possible[0] = true + + for l := range possible { + if !possible[l] { + continue + } + for i := range wordDict { + newLen := len(wordDict[i]) + l + if newLen > len(s) { + continue + } + if possible[newLen] { + continue + } + if s[l:newLen] == wordDict[i] { + possible[newLen] = true + } + } + } + + return possible[len(s)] +} + +var _ = wordBreak diff --git a/solutions/1/q153/solution.go b/solutions/1/q153/solution.go new file mode 100644 index 0000000..2ee45bc --- /dev/null +++ b/solutions/1/q153/solution.go @@ -0,0 +1,18 @@ +package q153 + +func findMin(nums []int) int { + l, r := 0, len(nums) + + for l < r && nums[l] > nums[r-1] { + m := (l + r) / 2 + if nums[m] > nums[r-1] { + l = m + 1 + } else { + r = m + 1 + l++ + } + } + return nums[l] +} + +var _ = findMin diff --git a/solutions/1/q162/solution.go b/solutions/1/q162/solution.go new file mode 100644 index 0000000..76ba592 --- /dev/null +++ b/solutions/1/q162/solution.go @@ -0,0 +1,24 @@ +package q162 + +// Important constraint: nums[i] != nums[i + 1] + +func findPeakElement(nums []int) int { + l, r := 0, len(nums) + for l < r { + m := (l + r) / 2 + + lLower := m == 0 || nums[m-1] < nums[m] + rLower := m == len(nums)-1 || nums[m+1] < nums[m] + if lLower && rLower { + return m + } + if !lLower { // left side is higher + r = m + } else { + l = m + 1 + } + } + return -1 +} + +var _ = findPeakElement diff --git a/solutions/2/q211/solution.go b/solutions/2/q211/solution.go new file mode 100644 index 0000000..cc453a2 --- /dev/null +++ b/solutions/2/q211/solution.go @@ -0,0 +1,63 @@ +package q211 + +type TrieNode struct { + word bool + next [26]*TrieNode +} + +func (n *TrieNode) hasMatch(pattern string, offset int) bool { + if n == nil { + return false + } + if offset == len(pattern) { + return n.word + } + + c := pattern[offset] + if c != '.' { + return n.next[toIdx(c)].hasMatch(pattern, offset+1) + } + + // Wildcard character + for _, t := range n.next { + if t != nil && t.hasMatch(pattern, offset+1) { + return true + } + } + + return false +} + +func toIdx(b byte) int8 { return int8(b - 'a') } + +type WordDictionary struct{ root *TrieNode } + +func Constructor() WordDictionary { + return WordDictionary{ + root: &TrieNode{}, + } +} + +func (d *WordDictionary) AddWord(word string) { + curr := d.root + for i := range len(word) { + c := word[i] + idx := toIdx(c) + if curr.next[idx] == nil { + curr.next[idx] = &TrieNode{} + } + curr = curr.next[idx] + } + curr.word = true +} + +func (d *WordDictionary) Search(word string) bool { + return d.root.hasMatch(word, 0) +} + +/** + * Your WordDictionary object will be instantiated and called as such: + * obj := Constructor(); + * obj.AddWord(word); + * param_2 := obj.Search(word); + */ diff --git a/solutions/2/q236/solution.go b/solutions/2/q236/solution.go new file mode 100644 index 0000000..add64ff --- /dev/null +++ b/solutions/2/q236/solution.go @@ -0,0 +1,31 @@ +package q236 + +type TreeNode struct { + Val int + Left *TreeNode + Right *TreeNode +} + +func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode { + if root == nil { + return nil + } + if root == p || root == q { + return root + } + + l := lowestCommonAncestor(root.Left, p, q) + r := lowestCommonAncestor(root.Right, p, q) + + switch { + case l == nil && r == nil: + return nil + case l != nil && r != nil: + return root + case l != nil: + return l + } + return r +} + +var _ = lowestCommonAncestor diff --git a/solutions/29/q2975/solution.go b/solutions/29/q2975/solution.go new file mode 100644 index 0000000..9acd316 --- /dev/null +++ b/solutions/29/q2975/solution.go @@ -0,0 +1,50 @@ +package q2975 + +import "slices" + +func maximizeSquareArea(m int, n int, hFences []int, vFences []int) int { + slices.Sort(hFences) + slices.Sort(vFences) + nHFences := len(hFences) + 2 + + lengths := make(map[int]struct{}, nHFences*(nHFences-1)/2) + for i := -1; i < len(hFences); i++ { + a := 1 + if i >= 0 { + a = hFences[i] + } + for j := i + 1; j <= len(hFences); j++ { + b := m + if j < len(hFences) { + b = hFences[j] + } + lengths[b-a] = struct{}{} + } + } + + maxEdge := -1 + for i := -1; i < len(vFences); i++ { + a := 1 + if i >= 0 { + a = vFences[i] + } + for j := i + 1; j <= len(vFences); j++ { + b := n + if j < len(vFences) { + b = vFences[j] + } + + if _, ok := lengths[b-a]; ok { + maxEdge = max(maxEdge, b-a) + } + } + } + if maxEdge == -1 { + return -1 + } + + maxEdge %= 1e9 + 7 + return (maxEdge * maxEdge) % (1e9 + 7) +} + +var _ = maximizeSquareArea diff --git a/solutions/3/q300/solution.go b/solutions/3/q300/solution.go new file mode 100644 index 0000000..badfa9f --- /dev/null +++ b/solutions/3/q300/solution.go @@ -0,0 +1,21 @@ +package q300 + +func lengthOfLIS(nums []int) int { + maxSeqLen := make([]int, len(nums)) + maxSeqLen[0] = 1 + globalMax := 1 + + for i := 1; i < len(nums); i++ { + locMax := 0 + for j := 0; j < i; j++ { + if nums[j] < nums[i] { + locMax = max(locMax, maxSeqLen[j]) + } + } + maxSeqLen[i] = locMax + 1 + globalMax = max(globalMax, maxSeqLen[i]) + } + return globalMax +} + +var _ = lengthOfLIS diff --git a/solutions/30/q3047/solution.go b/solutions/30/q3047/solution.go new file mode 100644 index 0000000..754d6aa --- /dev/null +++ b/solutions/30/q3047/solution.go @@ -0,0 +1,42 @@ +package q3047 + +import "slices" + +func intersectingSquareArea(bl1, tr1, bl2, tr2 []int) int64 { + l1, r1, l2, r2 := bl1[0], tr1[0], bl2[0], tr2[0] + iW := max(0, min(r1, r2)-max(l1, l2)) + + l1, r1, l2, r2 = bl1[1], tr1[1], bl2[1], tr2[1] + iH := max(0, min(r1, r2)-max(l1, l2)) + + edge := min(iW, iH) + return int64(edge * edge) +} + +func largestSquareArea(bottomLeft [][]int, topRight [][]int) int64 { + squares := make([]int, len(bottomLeft)) + for i := range squares { + squares[i] = i + } + slices.SortFunc(squares, // bottom-up order + func(a, b int) int { return bottomLeft[a][1] - bottomLeft[b][1] }) + + var largest int64 + + for i := range squares { + for j := i + 1; j < len(squares); j++ { + yI, yJ := topRight[squares[i]][1], bottomLeft[squares[j]][1] + if yJ >= yI { + break + } + + largest = max(largest, intersectingSquareArea( + bottomLeft[squares[i]], topRight[squares[i]], + bottomLeft[squares[j]], topRight[squares[j]], + )) + } + } + return largest +} + +var _ = largestSquareArea diff --git a/solutions/4/q427/solution.go b/solutions/4/q427/solution.go new file mode 100644 index 0000000..069753b --- /dev/null +++ b/solutions/4/q427/solution.go @@ -0,0 +1,44 @@ +package q427 + +type Node struct { + Val bool + IsLeaf bool + TopLeft *Node + TopRight *Node + BottomLeft *Node + BottomRight *Node +} + +func mkTree(grid [][]int, x, y, w int) *Node { + if w == 1 { + return &Node{ + Val: grid[y][x] == 1, + IsLeaf: true, + } + } + + subtreeW := w / 2 + node := &Node{ + TopLeft: mkTree(grid, x, y, subtreeW), + TopRight: mkTree(grid, x+subtreeW, y, subtreeW), + BottomLeft: mkTree(grid, x, y+subtreeW, subtreeW), + BottomRight: mkTree(grid, x+subtreeW, y+subtreeW, subtreeW), + } + if !node.TopLeft.IsLeaf || !node.TopRight.IsLeaf || !node.BottomLeft.IsLeaf || !node.BottomRight.IsLeaf { + return node + } + if node.TopLeft.Val && node.TopRight.Val && node.BottomLeft.Val && node.BottomRight.Val || + !node.TopLeft.Val && !node.TopRight.Val && !node.BottomLeft.Val && !node.BottomRight.Val { + return &Node{ + Val: node.TopLeft.Val, + IsLeaf: true, + } + } + return node +} + +func construct(grid [][]int) *Node { + return mkTree(grid, 0, 0, len(grid)) +} + +var _ = construct diff --git a/solutions/9/q986/solution.go b/solutions/9/q986/solution.go new file mode 100644 index 0000000..251a85b --- /dev/null +++ b/solutions/9/q986/solution.go @@ -0,0 +1,66 @@ +package q986 + +import "slices" + +type listElem struct { + x int + listId int8 // 0, 1 + isStart bool +} + +func intervalIntersection(firstList [][]int, secondList [][]int) [][]int { + locations := make([]listElem, 0, len(firstList)*2+len(secondList)*2) + + for i := range firstList { + locations = append( + locations, + listElem{x: firstList[i][0], listId: 0, isStart: true}, + listElem{x: firstList[i][1], listId: 0, isStart: false}, + ) + } + for i := range secondList { + locations = append( + locations, + listElem{x: secondList[i][0], listId: 1, isStart: true}, + listElem{x: secondList[i][1], listId: 1, isStart: false}, + ) + } + slices.SortFunc(locations, func(a, b listElem) int { + if a.x != b.x { + return a.x - b.x + } + if a.isStart { + return -1 + } + return 1 + }) + + ret := [][]int{} + start := 0 + isA, isB := false, false + for _, loc := range locations { + if loc.isStart { + start = loc.x + switch loc.listId { + case 0: + isA = true + default: + isB = true + } + } else { + if isA && isB { + ret = append(ret, []int{start, loc.x}) + } + switch loc.listId { + case 0: + isA = false + default: + isB = false + } + } + } + + return ret +} + +var _ = intervalIntersection