add new solutions
This commit is contained in:
parent
9c2c959a9b
commit
9a10695e8c
29 changed files with 1074 additions and 2 deletions
4
go.mod
4
go.mod
|
|
@ -10,6 +10,6 @@ require (
|
|||
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
|
||||
golang.org/x/sys v0.39.0 // indirect
|
||||
golang.org/x/text v0.32.0 // indirect
|
||||
)
|
||||
|
|
|
|||
4
go.sum
4
go.sum
|
|
@ -9,5 +9,9 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
|
|||
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=
|
||||
|
|
|
|||
27
solutions/0/q22/solution.go
Normal file
27
solutions/0/q22/solution.go
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
package q22
|
||||
|
||||
func gen(n, lvl, used int, buf []byte, ret []string) []string {
|
||||
if buf == nil {
|
||||
buf = make([]byte, 0, n*2)
|
||||
}
|
||||
if len(buf) == n*2 {
|
||||
return append(ret, string(buf))
|
||||
}
|
||||
|
||||
if used < n {
|
||||
buf = append(buf, '(')
|
||||
ret = gen(n, lvl+1, used+1, buf, ret)
|
||||
buf = buf[:len(buf)-1]
|
||||
}
|
||||
if lvl > 0 {
|
||||
buf = append(buf, ')')
|
||||
ret = gen(n, lvl-1, used, buf, ret)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func generateParenthesis(n int) []string {
|
||||
return gen(n, 0, 0, nil, nil)
|
||||
}
|
||||
|
||||
var _ = generateParenthesis
|
||||
51
solutions/0/q25/solution.go
Normal file
51
solutions/0/q25/solution.go
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
package q25
|
||||
|
||||
type ListNode struct {
|
||||
Val int
|
||||
Next *ListNode
|
||||
}
|
||||
|
||||
func reverse(begin *ListNode, k int) (newHead, newTail *ListNode) {
|
||||
tail := begin
|
||||
for range k - 1 {
|
||||
if tail.Next == nil {
|
||||
return begin, tail // no enough nodes
|
||||
}
|
||||
tail = tail.Next
|
||||
}
|
||||
|
||||
// Reverse
|
||||
cur := begin
|
||||
prev := tail.Next
|
||||
for range k - 1 {
|
||||
t := cur.Next
|
||||
cur.Next = prev
|
||||
prev, cur = cur, t
|
||||
}
|
||||
cur.Next = prev
|
||||
return cur, begin
|
||||
}
|
||||
|
||||
func reverseKGroup(head *ListNode, k int) *ListNode {
|
||||
if k < 2 {
|
||||
return head
|
||||
}
|
||||
|
||||
var ret, prevTail *ListNode
|
||||
p := head
|
||||
for p != nil {
|
||||
newHead, newTail := reverse(p, k)
|
||||
if ret == nil {
|
||||
ret = newHead
|
||||
}
|
||||
if prevTail != nil {
|
||||
prevTail.Next = newHead
|
||||
}
|
||||
prevTail = newTail
|
||||
p = newTail.Next
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
var _ = reverseKGroup
|
||||
36
solutions/0/q42/solution.go
Normal file
36
solutions/0/q42/solution.go
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
package q42
|
||||
|
||||
func trap(height []int) int {
|
||||
water := 0
|
||||
mid := 0
|
||||
|
||||
// From left
|
||||
maxHeight, stash := 0, 0
|
||||
for i, h := range height {
|
||||
if h >= maxHeight {
|
||||
maxHeight = h
|
||||
water += stash
|
||||
stash = 0
|
||||
mid = i
|
||||
} else {
|
||||
stash += maxHeight - h
|
||||
}
|
||||
}
|
||||
|
||||
// From right
|
||||
maxHeight, stash = 0, 0
|
||||
for i := len(height) - 1; i >= mid; i-- {
|
||||
h := height[i]
|
||||
if h >= maxHeight {
|
||||
maxHeight = h
|
||||
water += stash
|
||||
stash = 0
|
||||
} else {
|
||||
stash += maxHeight - h
|
||||
}
|
||||
}
|
||||
|
||||
return water
|
||||
}
|
||||
|
||||
var _ = trap
|
||||
37
solutions/0/q5/solution.go
Normal file
37
solutions/0/q5/solution.go
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
package q5
|
||||
|
||||
// Note: Although it can be done in O(N) with, e.g., Manacher's algorithm, the
|
||||
// input size is small enough to brute-force.
|
||||
|
||||
func expand(s string, l, r int) (int, int) {
|
||||
for l > 0 && r < len(s)-1 && s[l-1] == s[r+1] {
|
||||
l--
|
||||
r++
|
||||
}
|
||||
return l, r
|
||||
}
|
||||
|
||||
func longestPalindrome(s string) string {
|
||||
maxLen, mL, mR := 0, 0, 0
|
||||
|
||||
for c := range len(s) {
|
||||
l, r := expand(s, c, c)
|
||||
len_ := r - l + 1
|
||||
if len_ > maxLen {
|
||||
maxLen, mL, mR = len_, l, r
|
||||
}
|
||||
}
|
||||
|
||||
for c := range len(s) - 1 {
|
||||
if s[c] == s[c+1] {
|
||||
l, r := expand(s, c, c+1)
|
||||
len_ := r - l + 1
|
||||
if len_ > maxLen {
|
||||
maxLen, mL, mR = len_, l, r
|
||||
}
|
||||
}
|
||||
}
|
||||
return s[mL : mR+1]
|
||||
}
|
||||
|
||||
var _ = longestPalindrome
|
||||
25
solutions/0/q50/solution.go
Normal file
25
solutions/0/q50/solution.go
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
package q50
|
||||
|
||||
func myPow(x float64, n int) float64 {
|
||||
neg := n < 0
|
||||
if neg {
|
||||
n = -n
|
||||
}
|
||||
|
||||
var ret float64 = 1
|
||||
for n > 0 {
|
||||
v, p := x, 1
|
||||
for p*2 < n {
|
||||
p *= 2
|
||||
v *= v
|
||||
}
|
||||
n -= p
|
||||
ret *= v
|
||||
}
|
||||
if neg {
|
||||
return 1 / ret
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
var _ = myPow
|
||||
20
solutions/0/q56/solution.go
Normal file
20
solutions/0/q56/solution.go
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
package q56
|
||||
|
||||
import "slices"
|
||||
|
||||
func merge(intervals [][]int) [][]int {
|
||||
slices.SortFunc(intervals, func(a, b []int) int { return a[0] - b[0] })
|
||||
|
||||
p := 0
|
||||
for i := 1; i < len(intervals); i++ {
|
||||
if intervals[p][1] >= intervals[i][0] {
|
||||
intervals[p][1] = max(intervals[p][1], intervals[i][1])
|
||||
} else {
|
||||
p++
|
||||
intervals[p][0], intervals[p][1] = intervals[i][0], intervals[i][1]
|
||||
}
|
||||
}
|
||||
return intervals[:min(p+1, len(intervals))]
|
||||
}
|
||||
|
||||
var _ = merge
|
||||
29
solutions/0/q82/solution.go
Normal file
29
solutions/0/q82/solution.go
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
package q82
|
||||
|
||||
type ListNode struct {
|
||||
Val int
|
||||
Next *ListNode
|
||||
}
|
||||
|
||||
func deleteDuplicates(head *ListNode) *ListNode {
|
||||
root := ListNode{}
|
||||
last := &root
|
||||
|
||||
c := head
|
||||
for c != nil {
|
||||
if c.Next != nil && c.Next.Val == c.Val {
|
||||
dupVal := c.Val
|
||||
for c != nil && c.Val == dupVal {
|
||||
c = c.Next
|
||||
}
|
||||
continue
|
||||
}
|
||||
last.Next = c
|
||||
last = c
|
||||
c = c.Next
|
||||
last.Next = nil
|
||||
}
|
||||
return root.Next
|
||||
}
|
||||
|
||||
var _ = deleteDuplicates
|
||||
35
solutions/1/q105/solution.go
Normal file
35
solutions/1/q105/solution.go
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
package q105
|
||||
|
||||
type TreeNode struct {
|
||||
Val int
|
||||
Left *TreeNode
|
||||
Right *TreeNode
|
||||
}
|
||||
|
||||
func bld(preorder []int, inorder map[int]int, pL, pR, iL, iR int) *TreeNode {
|
||||
if pL == pR {
|
||||
return nil
|
||||
}
|
||||
|
||||
val := preorder[pL]
|
||||
p := inorder[val] // position of val in "inorder"
|
||||
|
||||
left := bld(preorder, inorder, pL+1, pL+1+p-iL, iL, p)
|
||||
right := bld(preorder, inorder, pL+1+p-iL, pR, p+1, iR)
|
||||
|
||||
return &TreeNode{
|
||||
Val: val,
|
||||
Left: left,
|
||||
Right: right,
|
||||
}
|
||||
}
|
||||
|
||||
func buildTree(preorder []int, inorder []int) *TreeNode {
|
||||
iIdx := make(map[int]int, len(inorder))
|
||||
for i := range inorder {
|
||||
iIdx[inorder[i]] = i
|
||||
}
|
||||
return bld(preorder, iIdx, 0, len(preorder), 0, len(preorder))
|
||||
}
|
||||
|
||||
var _ = buildTree
|
||||
35
solutions/1/q114/solution.go
Normal file
35
solutions/1/q114/solution.go
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
package q114
|
||||
|
||||
type TreeNode struct {
|
||||
Val int
|
||||
Left *TreeNode
|
||||
Right *TreeNode
|
||||
}
|
||||
|
||||
func fl(node *TreeNode) (head, tail *TreeNode) {
|
||||
if node == nil {
|
||||
return nil, nil
|
||||
}
|
||||
head, tail = node, node
|
||||
|
||||
lhead, ltail := fl(node.Left)
|
||||
rhead, rtail := fl(node.Right)
|
||||
|
||||
if lhead != nil {
|
||||
node.Left = nil
|
||||
node.Right = lhead
|
||||
tail = ltail
|
||||
}
|
||||
|
||||
if rhead != nil {
|
||||
tail.Right = rhead
|
||||
tail = rtail
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func flatten(root *TreeNode) {
|
||||
fl(root)
|
||||
}
|
||||
|
||||
var _ = flatten
|
||||
63
solutions/1/q127/solution.go
Normal file
63
solutions/1/q127/solution.go
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
package q127
|
||||
|
||||
// Ideas for improvement: use a hashmap to index strings instead of an O(n^2)
|
||||
// comparison and neighbor matrix; use bidirectional BFS.
|
||||
|
||||
func reachable(a, b string) bool {
|
||||
diff := false
|
||||
for i := range len(a) {
|
||||
if a[i] != b[i] {
|
||||
if diff {
|
||||
return false
|
||||
}
|
||||
diff = true
|
||||
}
|
||||
}
|
||||
return diff // exactly one different char
|
||||
}
|
||||
|
||||
func ladderLength(beginWord string, endWord string, wordList []string) int {
|
||||
target := -1
|
||||
neighbors := make([][]int, len(wordList))
|
||||
|
||||
for i := range wordList {
|
||||
if target == -1 && wordList[i] == endWord {
|
||||
target = i
|
||||
}
|
||||
for j := i + 1; j < len(wordList); j++ {
|
||||
if reachable(wordList[i], wordList[j]) {
|
||||
neighbors[i] = append(neighbors[i], j)
|
||||
neighbors[j] = append(neighbors[j], i)
|
||||
}
|
||||
}
|
||||
}
|
||||
if target == -1 {
|
||||
return 0
|
||||
}
|
||||
|
||||
seen := make([]bool, len(wordList))
|
||||
queue := make([][2]int, 0, len(wordList)) // index, steps
|
||||
for i := range wordList {
|
||||
if reachable(beginWord, wordList[i]) {
|
||||
seen[i] = true
|
||||
queue = append(queue, [2]int{i, 2})
|
||||
}
|
||||
}
|
||||
for ; len(queue) > 0; queue = queue[1:] {
|
||||
id, step := queue[0][0], queue[0][1]
|
||||
if id == target {
|
||||
return step
|
||||
}
|
||||
|
||||
for _, n := range neighbors[id] {
|
||||
if !seen[n] {
|
||||
seen[n] = true
|
||||
queue = append(queue, [2]int{n, step + 1})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
var _ = ladderLength
|
||||
39
solutions/1/q133/solution.go
Normal file
39
solutions/1/q133/solution.go
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
package q133
|
||||
|
||||
type Node struct {
|
||||
Val int
|
||||
Neighbors []*Node
|
||||
}
|
||||
|
||||
func cloneGraph(node *Node) *Node {
|
||||
if node == nil {
|
||||
return nil
|
||||
}
|
||||
seen := map[*Node]*Node{}
|
||||
|
||||
queue := []*Node{node}
|
||||
for ; len(queue) > 0; queue = queue[1:] {
|
||||
cur := queue[0]
|
||||
if _, ok := seen[cur]; ok {
|
||||
continue
|
||||
}
|
||||
cloned := &Node{
|
||||
Val: cur.Val,
|
||||
Neighbors: []*Node{},
|
||||
}
|
||||
seen[cur] = cloned
|
||||
for _, n := range cur.Neighbors {
|
||||
if nCloned, ok := seen[n]; ok {
|
||||
// Link
|
||||
cloned.Neighbors = append(cloned.Neighbors, nCloned)
|
||||
nCloned.Neighbors = append(nCloned.Neighbors, cloned)
|
||||
} else {
|
||||
// Add to queue
|
||||
queue = append(queue, n)
|
||||
}
|
||||
}
|
||||
}
|
||||
return seen[node]
|
||||
}
|
||||
|
||||
var _ = cloneGraph
|
||||
22
solutions/1/q137/solution.go
Normal file
22
solutions/1/q137/solution.go
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
package q137
|
||||
|
||||
func singleNumber(nums []int) int {
|
||||
bitCounts := make([]uint8, 32)
|
||||
for _, num := range nums {
|
||||
num32 := int32(num)
|
||||
for i := range 32 {
|
||||
if num32|1<<i == num32 {
|
||||
bitCounts[i] = (bitCounts[i] + 1) % 3
|
||||
}
|
||||
}
|
||||
}
|
||||
var ret int32
|
||||
for i := range 32 {
|
||||
if bitCounts[i] != 0 {
|
||||
ret |= 1 << i
|
||||
}
|
||||
}
|
||||
return int(ret)
|
||||
}
|
||||
|
||||
var _ = singleNumber
|
||||
112
solutions/1/q146/solution.go
Normal file
112
solutions/1/q146/solution.go
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
package q146
|
||||
|
||||
type lruNode struct {
|
||||
key, val int
|
||||
prev, next *lruNode
|
||||
}
|
||||
|
||||
type LRUCache struct {
|
||||
cap int
|
||||
index map[int]*lruNode
|
||||
head, tail *lruNode
|
||||
|
||||
nodes []lruNode
|
||||
p int
|
||||
}
|
||||
|
||||
func Constructor(capacity int) LRUCache {
|
||||
return LRUCache{
|
||||
cap: capacity,
|
||||
index: make(map[int]*lruNode, capacity),
|
||||
nodes: make([]lruNode, capacity),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *LRUCache) alloc() *lruNode {
|
||||
if c.p < len(c.nodes) {
|
||||
c.p++
|
||||
return &c.nodes[c.p-1]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *LRUCache) touch(node *lruNode) {
|
||||
if node.prev == nil {
|
||||
return
|
||||
}
|
||||
if c.tail == node {
|
||||
c.tail = node.prev
|
||||
} else {
|
||||
node.next.prev = node.prev
|
||||
}
|
||||
node.prev.next = node.next
|
||||
|
||||
node.prev = nil
|
||||
node.next = c.head
|
||||
c.head.prev = node
|
||||
c.head = node
|
||||
}
|
||||
|
||||
func (c *LRUCache) evict() *lruNode {
|
||||
if len(c.index) < c.cap {
|
||||
return nil
|
||||
}
|
||||
|
||||
node := c.tail
|
||||
delete(c.index, node.key)
|
||||
|
||||
if node.prev == nil {
|
||||
c.head, c.tail = nil, nil
|
||||
} else {
|
||||
c.tail = node.prev
|
||||
c.tail.next = nil
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
func (c *LRUCache) Get(key int) int {
|
||||
node := c.index[key]
|
||||
if node == nil {
|
||||
return -1
|
||||
}
|
||||
c.touch(node)
|
||||
return node.val
|
||||
}
|
||||
|
||||
func (c *LRUCache) Put(key int, value int) {
|
||||
if c.cap == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
node := c.index[key]
|
||||
if node != nil {
|
||||
node.val = value
|
||||
c.touch(node)
|
||||
return
|
||||
}
|
||||
|
||||
node = c.alloc()
|
||||
if node == nil {
|
||||
node = c.evict()
|
||||
*node = lruNode{} // clear
|
||||
}
|
||||
|
||||
node.key, node.val = key, value
|
||||
c.index[key] = node
|
||||
|
||||
node.next = c.head
|
||||
if c.head != nil {
|
||||
c.head.prev = node
|
||||
}
|
||||
c.head = node
|
||||
if c.tail == nil {
|
||||
c.tail = node
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Your LRUCache object will be instantiated and called as such:
|
||||
* obj := Constructor(capacity);
|
||||
* param_1 := obj.Get(key);
|
||||
* obj.Put(key,value);
|
||||
*/
|
||||
19
solutions/1/q151/solution.go
Normal file
19
solutions/1/q151/solution.go
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
package q151
|
||||
|
||||
import "strings"
|
||||
|
||||
func reverseWords(s string) string {
|
||||
b := strings.Builder{}
|
||||
fields := strings.Fields(s)
|
||||
if len(fields) > 0 {
|
||||
b.WriteString(fields[len(fields)-1])
|
||||
}
|
||||
for i := len(fields) - 2; i >= 0; i-- {
|
||||
b.WriteByte(' ')
|
||||
b.WriteString(fields[i])
|
||||
}
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
var _ = reverseWords
|
||||
44
solutions/1/q155/solution.go
Normal file
44
solutions/1/q155/solution.go
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
package q155
|
||||
|
||||
type stackElem struct {
|
||||
val, min int
|
||||
}
|
||||
|
||||
type MinStack struct {
|
||||
stack []stackElem
|
||||
}
|
||||
|
||||
func Constructor() MinStack {
|
||||
return MinStack{}
|
||||
}
|
||||
|
||||
func (s *MinStack) Push(val int) {
|
||||
minVal := val
|
||||
if len(s.stack) > 0 {
|
||||
minVal = min(minVal, s.GetMin())
|
||||
}
|
||||
s.stack = append(s.stack, stackElem{
|
||||
val: val, min: minVal,
|
||||
})
|
||||
}
|
||||
|
||||
func (s *MinStack) Pop() {
|
||||
s.stack = s.stack[:len(s.stack)-1]
|
||||
}
|
||||
|
||||
func (s *MinStack) Top() int {
|
||||
return s.stack[len(s.stack)-1].val
|
||||
}
|
||||
|
||||
func (s *MinStack) GetMin() int {
|
||||
return s.stack[len(s.stack)-1].min
|
||||
}
|
||||
|
||||
/**
|
||||
* Your MinStack object will be instantiated and called as such:
|
||||
* obj := Constructor();
|
||||
* obj.Push(val);
|
||||
* obj.Pop();
|
||||
* param_3 := obj.Top();
|
||||
* param_4 := obj.GetMin();
|
||||
*/
|
||||
21
solutions/1/q172/solution.go
Normal file
21
solutions/1/q172/solution.go
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
package q172
|
||||
|
||||
// Note: actually, counting 5 alone is enough since 2 certainly occurs more than 5.
|
||||
|
||||
func trailingZeroes(n int) int {
|
||||
count2, count5 := 0, 0
|
||||
for i := 2; i <= n; i++ {
|
||||
num := i
|
||||
for num%2 == 0 {
|
||||
num /= 2
|
||||
count2++
|
||||
}
|
||||
for num%5 == 0 {
|
||||
num /= 5
|
||||
count5++
|
||||
}
|
||||
}
|
||||
return min(count2, count5)
|
||||
}
|
||||
|
||||
var _ = trailingZeroes
|
||||
13
solutions/1/q198/solution.go
Normal file
13
solutions/1/q198/solution.go
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
package q198
|
||||
|
||||
func rob(nums []int) int {
|
||||
if len(nums) > 1 {
|
||||
nums[1] = max(nums[0], nums[1])
|
||||
}
|
||||
for i := 2; i < len(nums); i++ {
|
||||
nums[i] = max(nums[i-2]+nums[i], nums[i-1])
|
||||
}
|
||||
return nums[len(nums)-1]
|
||||
}
|
||||
|
||||
var _ = rob
|
||||
43
solutions/11/q1161/solution.go
Normal file
43
solutions/11/q1161/solution.go
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
package q1161
|
||||
|
||||
import "math"
|
||||
|
||||
type TreeNode struct {
|
||||
Val int
|
||||
Left *TreeNode
|
||||
Right *TreeNode
|
||||
}
|
||||
|
||||
func maxLevelSum(root *TreeNode) int {
|
||||
type qElem struct {
|
||||
node *TreeNode
|
||||
level int
|
||||
}
|
||||
queue := make([]qElem, 0, 256)
|
||||
queue = append(queue, qElem{root, 1})
|
||||
|
||||
maxSum, maxLvl := math.MinInt, 0
|
||||
sum, lvl := 0, 1
|
||||
for ; len(queue) > 0; queue = queue[1:] {
|
||||
cur := &queue[0]
|
||||
if cur.level != lvl {
|
||||
if sum > maxSum {
|
||||
maxSum, maxLvl = sum, lvl
|
||||
}
|
||||
sum, lvl = 0, cur.level
|
||||
}
|
||||
sum += cur.node.Val
|
||||
if cur.node.Left != nil {
|
||||
queue = append(queue, qElem{cur.node.Left, cur.level + 1})
|
||||
}
|
||||
if cur.node.Right != nil {
|
||||
queue = append(queue, qElem{cur.node.Right, cur.level + 1})
|
||||
}
|
||||
}
|
||||
if sum > maxSum {
|
||||
return lvl
|
||||
}
|
||||
return maxLvl
|
||||
}
|
||||
|
||||
var _ = maxLevelSum
|
||||
45
solutions/13/q1339/solution.go
Normal file
45
solutions/13/q1339/solution.go
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
package q1339
|
||||
|
||||
type TreeNode struct {
|
||||
Val int
|
||||
Left *TreeNode
|
||||
Right *TreeNode
|
||||
}
|
||||
|
||||
func sumSumTrees(node *TreeNode) int {
|
||||
if node == nil {
|
||||
return 0
|
||||
}
|
||||
node.Val += sumSumTrees(node.Left) + sumSumTrees(node.Right)
|
||||
return node.Val
|
||||
}
|
||||
|
||||
func findNearest(node *TreeNode, target int) int {
|
||||
if node == nil {
|
||||
return -1
|
||||
}
|
||||
ret := node.Val
|
||||
l, r := findNearest(node.Left, target), findNearest(node.Right, target)
|
||||
if abs(l-target) < abs(ret-target) {
|
||||
ret = l
|
||||
}
|
||||
if abs(r-target) < abs(ret-target) {
|
||||
ret = r
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func abs(n int) int {
|
||||
if n < 0 {
|
||||
return -n
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func maxProduct(root *TreeNode) int {
|
||||
totalSum := sumSumTrees(root)
|
||||
nearest := findNearest(root, totalSum/2)
|
||||
return nearest * (totalSum - nearest) % (1e9 + 7)
|
||||
}
|
||||
|
||||
var _ = maxProduct
|
||||
40
solutions/19/q1975/solution.go
Normal file
40
solutions/19/q1975/solution.go
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
package q1975
|
||||
|
||||
import "math"
|
||||
|
||||
func abs(i int) int {
|
||||
if i < 0 {
|
||||
return -i
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
func maxMatrixSum(matrix [][]int) int64 {
|
||||
var sum int64
|
||||
min_ := math.MaxInt
|
||||
hasZero := false
|
||||
nNeg := 0
|
||||
|
||||
for i := range matrix {
|
||||
for _, num := range matrix[i] {
|
||||
if num < 0 {
|
||||
nNeg++
|
||||
}
|
||||
if num == 0 {
|
||||
hasZero = true
|
||||
}
|
||||
num = abs(num)
|
||||
sum += int64(num)
|
||||
if num < min_ {
|
||||
min_ = num
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if hasZero || nNeg%2 == 0 {
|
||||
return sum
|
||||
}
|
||||
return sum - 2*int64(min_)
|
||||
}
|
||||
|
||||
var _ = maxMatrixSum
|
||||
37
solutions/2/q207/solution.go
Normal file
37
solutions/2/q207/solution.go
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
package q207
|
||||
|
||||
func canFinish(numCourses int, prerequisites [][]int) bool {
|
||||
nDeps := make([]int, numCourses)
|
||||
revDeps := make([][]int, numCourses)
|
||||
|
||||
for i := range prerequisites {
|
||||
course, prereq := prerequisites[i][0], prerequisites[i][1]
|
||||
nDeps[course]++
|
||||
revDeps[prereq] = append(revDeps[prereq], course)
|
||||
}
|
||||
|
||||
queue := []int{}
|
||||
for i := range numCourses {
|
||||
if nDeps[i] == 0 && len(revDeps) > 0 {
|
||||
queue = append(queue, i)
|
||||
}
|
||||
}
|
||||
for ; len(queue) > 0; queue = queue[1:] {
|
||||
course := queue[0]
|
||||
for _, r := range revDeps[course] {
|
||||
nDeps[r]--
|
||||
if nDeps[r] == 0 {
|
||||
queue = append(queue, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, n := range nDeps {
|
||||
if n > 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
var _ = canFinish
|
||||
89
solutions/2/q212/solution.go
Normal file
89
solutions/2/q212/solution.go
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
package q212
|
||||
|
||||
type TrieNode struct {
|
||||
children [26]*TrieNode
|
||||
word *string
|
||||
}
|
||||
|
||||
func trieIdx(char byte) int8 {
|
||||
if char < 'a' || char > 'z' {
|
||||
return -1
|
||||
}
|
||||
return int8(char - 'a')
|
||||
}
|
||||
|
||||
func allocator(bulkSize int) func() *TrieNode {
|
||||
var v []TrieNode
|
||||
p := 0
|
||||
|
||||
return func() *TrieNode {
|
||||
if v == nil || p == bulkSize {
|
||||
v = make([]TrieNode, bulkSize)
|
||||
p = 0
|
||||
}
|
||||
p++
|
||||
return &v[p-1]
|
||||
}
|
||||
}
|
||||
|
||||
func buildTrie(words []string) *TrieNode {
|
||||
alloc := allocator(128)
|
||||
root := alloc()
|
||||
for _, word := range words {
|
||||
p := root
|
||||
for i := range len(word) {
|
||||
idx := trieIdx(word[i])
|
||||
if idx < 0 {
|
||||
continue
|
||||
}
|
||||
if p.children[idx] == nil {
|
||||
p.children[idx] = alloc()
|
||||
}
|
||||
p = p.children[idx]
|
||||
}
|
||||
p.word = &word
|
||||
}
|
||||
return root
|
||||
}
|
||||
|
||||
type Coord [2]int8
|
||||
|
||||
func find(board [][]byte, coord Coord, trie *TrieNode, found *[]string) {
|
||||
if coord[0] < 0 || coord[1] < 0 ||
|
||||
int(coord[0]) >= len(board) || int(coord[1]) >= len(board[0]) {
|
||||
return
|
||||
}
|
||||
c := board[coord[0]][coord[1]]
|
||||
idx := trieIdx(c)
|
||||
if idx == -1 || trie.children[idx] == nil {
|
||||
return
|
||||
}
|
||||
// Mark visited
|
||||
board[coord[0]][coord[1]] = '.'
|
||||
|
||||
trie = trie.children[idx]
|
||||
if trie.word != nil {
|
||||
*found = append(*found, *trie.word)
|
||||
trie.word = nil // dedup
|
||||
}
|
||||
|
||||
find(board, Coord{coord[0] + 1, coord[1]}, trie, found)
|
||||
find(board, Coord{coord[0] - 1, coord[1]}, trie, found)
|
||||
find(board, Coord{coord[0], coord[1] + 1}, trie, found)
|
||||
find(board, Coord{coord[0], coord[1] - 1}, trie, found)
|
||||
board[coord[0]][coord[1]] = c
|
||||
}
|
||||
|
||||
func findWords(board [][]byte, words []string) []string {
|
||||
trie := buildTrie(words)
|
||||
found := []string{}
|
||||
|
||||
for row := range board {
|
||||
for col := range board[0] {
|
||||
find(board, Coord{int8(row), int8(col)}, trie, &found)
|
||||
}
|
||||
}
|
||||
return found
|
||||
}
|
||||
|
||||
var _ = findWords
|
||||
26
solutions/2/q221/solution.go
Normal file
26
solutions/2/q221/solution.go
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
package q221
|
||||
|
||||
func maximalSquare(matrix [][]byte) int {
|
||||
w, h := len(matrix[0]), len(matrix)
|
||||
|
||||
maxSq := make([]int16, w+h)
|
||||
maxV := make([]int16, w)
|
||||
ret := 0
|
||||
for y := range h {
|
||||
var maxH int16
|
||||
for x := range w {
|
||||
if matrix[y][x] == '0' {
|
||||
maxH, maxV[x], maxSq[x-y+h] = 0, 0, 0
|
||||
continue
|
||||
}
|
||||
|
||||
maxH++
|
||||
maxV[x]++
|
||||
maxSq[x-y+h] = min(maxH, maxV[x], maxSq[x-y+h]+1)
|
||||
ret = max(ret, int(maxSq[x-y+h]))
|
||||
}
|
||||
}
|
||||
return ret * ret
|
||||
}
|
||||
|
||||
var _ = maximalSquare
|
||||
35
solutions/2/q230/solution.go
Normal file
35
solutions/2/q230/solution.go
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
package q230
|
||||
|
||||
type TreeNode struct {
|
||||
Val int
|
||||
Left *TreeNode
|
||||
Right *TreeNode
|
||||
}
|
||||
|
||||
func findKth(node *TreeNode, k, current int) (int, *int) {
|
||||
if node == nil {
|
||||
return current, nil
|
||||
}
|
||||
|
||||
current, ret := findKth(node.Left, k, current)
|
||||
if ret != nil {
|
||||
return current, ret
|
||||
}
|
||||
|
||||
current += 1
|
||||
if current == k {
|
||||
return current, &node.Val
|
||||
}
|
||||
|
||||
return findKth(node.Right, k, current)
|
||||
}
|
||||
|
||||
func kthSmallest(root *TreeNode, k int) int {
|
||||
_, kth := findKth(root, k, 0)
|
||||
if kth == nil {
|
||||
return 0
|
||||
}
|
||||
return *kth
|
||||
}
|
||||
|
||||
var _ = kthSmallest
|
||||
31
solutions/3/q322/solution.go
Normal file
31
solutions/3/q322/solution.go
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
package q322
|
||||
|
||||
// Note: The cache size only needs to be min(max(coins), amount).
|
||||
|
||||
func coinChange(coins []int, amount int) int {
|
||||
if amount == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
cache := make([]int, amount+1)
|
||||
cache[0] = amount + 1
|
||||
for p := 1; p < len(cache); p *= 2 {
|
||||
copy(cache[p:], cache[:p]) // fill with MAX+1
|
||||
}
|
||||
cache[0] = 0
|
||||
|
||||
for i := 1; i < len(cache); i++ {
|
||||
for _, c := range coins {
|
||||
if (i - c) < 0 {
|
||||
continue
|
||||
}
|
||||
cache[i] = min(cache[i], cache[i-c]+1)
|
||||
}
|
||||
}
|
||||
if cache[amount] > amount {
|
||||
return -1
|
||||
}
|
||||
return cache[amount]
|
||||
}
|
||||
|
||||
var _ = coinChange
|
||||
71
solutions/4/q433/solution.go
Normal file
71
solutions/4/q433/solution.go
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
package q433
|
||||
|
||||
import "slices"
|
||||
|
||||
func canMutate(a, b string) bool {
|
||||
diff := false
|
||||
for i := range len(a) {
|
||||
if a[i] != b[i] {
|
||||
if diff {
|
||||
return false
|
||||
}
|
||||
diff = true
|
||||
}
|
||||
}
|
||||
return diff // exactly one mutation
|
||||
}
|
||||
|
||||
func minMutation(startGene string, endGene string, bank []string) int {
|
||||
reachables := make([][]int, len(bank))
|
||||
initial := []int{}
|
||||
target := -1
|
||||
for i := range len(bank) - 1 {
|
||||
for j := i + 1; j < len(bank); j++ {
|
||||
if canMutate(bank[i], bank[j]) {
|
||||
reachables[i] = append(reachables[i], j)
|
||||
reachables[j] = append(reachables[j], i)
|
||||
}
|
||||
}
|
||||
}
|
||||
for i := range bank {
|
||||
if bank[i] == endGene {
|
||||
target = i
|
||||
}
|
||||
if canMutate(startGene, bank[i]) {
|
||||
if i == target {
|
||||
return 1
|
||||
}
|
||||
initial = append(initial, i)
|
||||
}
|
||||
}
|
||||
if target == -1 {
|
||||
return -1
|
||||
}
|
||||
|
||||
type qElem struct {
|
||||
path []int
|
||||
}
|
||||
queue := make([]qElem, 0, len(initial)*2)
|
||||
for _, i := range initial {
|
||||
queue = append(queue, qElem{path: []int{i}})
|
||||
}
|
||||
|
||||
for ; len(queue) > 0; queue = queue[1:] {
|
||||
cur := queue[0].path
|
||||
last := cur[len(cur)-1]
|
||||
next := reachables[last]
|
||||
for _, n := range next {
|
||||
if n == target {
|
||||
return len(cur) + 1
|
||||
}
|
||||
if slices.Contains(cur, n) {
|
||||
continue
|
||||
}
|
||||
queue = append(queue, qElem{path: append(cur, n)})
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
var _ = minMutation
|
||||
23
solutions/4/q452/solution.go
Normal file
23
solutions/4/q452/solution.go
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
package q452
|
||||
|
||||
import "slices"
|
||||
|
||||
func findMinArrowShots(points [][]int) int {
|
||||
slices.SortFunc(points, func(a, b []int) int { return a[0] - b[0] })
|
||||
arrows := 1
|
||||
prev := points[0]
|
||||
|
||||
for i := 1; i < len(points); i++ {
|
||||
cur := points[i]
|
||||
if cur[0] > prev[1] {
|
||||
arrows++
|
||||
prev = cur
|
||||
continue
|
||||
}
|
||||
prev[0] = max(prev[0], cur[0])
|
||||
prev[1] = min(prev[1], cur[1])
|
||||
}
|
||||
return arrows
|
||||
}
|
||||
|
||||
var _ = findMinArrowShots
|
||||
Loading…
Add table
Add a link
Reference in a new issue