feat: osijvrsoi
This commit is contained in:
11
pkg/questions/best_time_to_buy_and_sell_stock/main.go
Normal file
11
pkg/questions/best_time_to_buy_and_sell_stock/main.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package besttimetobuyandsellstock
|
||||
|
||||
func MaxProfit(prices []int) int {
|
||||
buy, sell := 1_000_000_000, 0
|
||||
|
||||
for _, price := range prices {
|
||||
buy, sell = min(buy, price), max(sell, price-buy)
|
||||
}
|
||||
|
||||
return sell
|
||||
}
|
||||
105
pkg/questions/car_fleet/main.go
Normal file
105
pkg/questions/car_fleet/main.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package car_fleet
|
||||
|
||||
import (
|
||||
"math"
|
||||
"slices"
|
||||
)
|
||||
|
||||
type Car struct {
|
||||
Position float64
|
||||
Speed float64
|
||||
}
|
||||
|
||||
// The TIME at which the two cars will collide with each other.
|
||||
func (c Car) CollidesInto(o Car) float64 {
|
||||
if c.Speed == o.Speed {
|
||||
return math.Inf(1)
|
||||
}
|
||||
return float64(c.Position-o.Position) / float64(o.Speed-c.Speed)
|
||||
}
|
||||
|
||||
// The DISTANCE the car will be at a point in time.
|
||||
func (c Car) At(time float64) float64 {
|
||||
return c.Position + c.Speed*time
|
||||
}
|
||||
|
||||
// The TIME the car will reach a certain distance.
|
||||
func (c Car) Reaches(target float64) float64 {
|
||||
if c.Speed == 0 {
|
||||
return math.Inf(1)
|
||||
}
|
||||
|
||||
return (target - c.Position) / c.Speed
|
||||
}
|
||||
|
||||
type Interval struct {
|
||||
From float64
|
||||
To float64
|
||||
}
|
||||
|
||||
func (i Interval) Contains(point float64) bool {
|
||||
return point >= i.From && point <= i.To
|
||||
}
|
||||
|
||||
func (i Interval) Intersect(o Interval) Interval {
|
||||
return Interval{
|
||||
From: max(i.From, o.From),
|
||||
To: min(i.To, o.To),
|
||||
}
|
||||
}
|
||||
|
||||
type Trajectory struct {
|
||||
Car
|
||||
Interval
|
||||
}
|
||||
|
||||
func sortByInversePosition(a Car, b Car) int {
|
||||
return int(b.Position - a.Position)
|
||||
}
|
||||
|
||||
func CarFleet(target int, position []int, speed []int) int {
|
||||
cars := []Car{}
|
||||
ends := map[float64]bool{}
|
||||
|
||||
for i := range position {
|
||||
cars = append(cars, Car{
|
||||
Position: float64(position[i]),
|
||||
Speed: float64(speed[i]),
|
||||
})
|
||||
}
|
||||
|
||||
slices.SortFunc(cars, sortByInversePosition)
|
||||
stack := []Trajectory{}
|
||||
|
||||
for _, car := range cars {
|
||||
fastest_trajectory := Trajectory{
|
||||
Car: car,
|
||||
Interval: Interval{
|
||||
From: 0,
|
||||
To: car.Reaches(float64(target)),
|
||||
},
|
||||
}
|
||||
|
||||
for {
|
||||
if len(stack) == 0 {
|
||||
stack = append(stack, fastest_trajectory)
|
||||
break
|
||||
}
|
||||
|
||||
first_trajectory := stack[len(stack)-1]
|
||||
collision_time := car.CollidesInto(first_trajectory.Car)
|
||||
if fastest_trajectory.Intersect(first_trajectory.Interval).Contains(collision_time) {
|
||||
first_trajectory.From = collision_time
|
||||
fastest_trajectory.To = collision_time
|
||||
stack = append(stack, fastest_trajectory)
|
||||
break
|
||||
}
|
||||
|
||||
stack = stack[:len(stack)-1]
|
||||
}
|
||||
|
||||
ends[stack[0].To] = true
|
||||
}
|
||||
|
||||
return len(ends)
|
||||
}
|
||||
44
pkg/questions/car_fleet/main_test.go
Normal file
44
pkg/questions/car_fleet/main_test.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package car_fleet_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.maximhutz.com/practice/pkg/car_fleet"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test1(t *testing.T) {
|
||||
target := 12
|
||||
position := []int{10, 8, 0, 5, 3}
|
||||
speed := []int{2, 4, 1, 1, 3}
|
||||
output := 3
|
||||
|
||||
assert.Equal(t, output, car_fleet.CarFleet(target, position, speed))
|
||||
}
|
||||
|
||||
func Test2(t *testing.T) {
|
||||
target := 10
|
||||
position := []int{3}
|
||||
speed := []int{3}
|
||||
output := 1
|
||||
|
||||
assert.Equal(t, output, car_fleet.CarFleet(target, position, speed))
|
||||
}
|
||||
|
||||
func Test3(t *testing.T) {
|
||||
target := 100
|
||||
position := []int{0, 2, 4}
|
||||
speed := []int{4, 2, 1}
|
||||
output := 1
|
||||
|
||||
assert.Equal(t, output, car_fleet.CarFleet(target, position, speed))
|
||||
}
|
||||
|
||||
func Test4(t *testing.T) {
|
||||
target := 10
|
||||
position := []int{6, 8}
|
||||
speed := []int{3, 2}
|
||||
output := 2
|
||||
|
||||
assert.Equal(t, output, car_fleet.CarFleet(target, position, speed))
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package constructbinarytreefrompreorderandinordertraversal
|
||||
|
||||
type TreeNode struct {
|
||||
Val int
|
||||
Left *TreeNode
|
||||
Right *TreeNode
|
||||
}
|
||||
|
||||
type NodeInfo struct {
|
||||
Val int
|
||||
Preorder int
|
||||
Inorder int
|
||||
}
|
||||
|
||||
func buildTreeInfo(info []NodeInfo) *TreeNode {
|
||||
if len(info) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
root_info := info[0]
|
||||
for _, datum := range info {
|
||||
if datum.Preorder < root_info.Preorder {
|
||||
root_info = datum
|
||||
}
|
||||
}
|
||||
|
||||
left_info := []NodeInfo{}
|
||||
right_info := []NodeInfo{}
|
||||
for _, datum := range info {
|
||||
if datum.Inorder < root_info.Inorder {
|
||||
left_info = append(left_info, datum)
|
||||
} else if datum.Inorder > root_info.Inorder {
|
||||
right_info = append(right_info, datum)
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return &TreeNode{
|
||||
Val: root_info.Val,
|
||||
Left: buildTreeInfo(left_info),
|
||||
Right: buildTreeInfo(right_info),
|
||||
}
|
||||
}
|
||||
|
||||
func buildTree(preorder []int, inorder []int) *TreeNode {
|
||||
info_map := map[int]*NodeInfo{}
|
||||
for o, v := range preorder {
|
||||
info_map[v] = &NodeInfo{
|
||||
Val: v,
|
||||
Preorder: o,
|
||||
}
|
||||
}
|
||||
|
||||
for o, v := range inorder {
|
||||
info_map[v].Inorder = o
|
||||
}
|
||||
|
||||
info := []NodeInfo{}
|
||||
for _, datum := range info_map {
|
||||
info = append(info, *datum)
|
||||
}
|
||||
|
||||
return buildTreeInfo(info)
|
||||
}
|
||||
36
pkg/questions/container_with_most_water/main.go
Normal file
36
pkg/questions/container_with_most_water/main.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package container_with_most_water
|
||||
|
||||
func MaxArea(height []int) int {
|
||||
if len(height) < 2 {
|
||||
return 0
|
||||
}
|
||||
|
||||
start := 0
|
||||
end := len(height) - 1
|
||||
|
||||
// Let:
|
||||
// - A = the smaller side,
|
||||
// - B = the larger side.
|
||||
//
|
||||
// Notice that:
|
||||
// - Any container with A cannot have a height larger than `min(A, B)`.
|
||||
// - Any container with A cannot have a width larger than `B - A`.
|
||||
//
|
||||
// Because of this, all solutions containing A cannot be larger than `area`.
|
||||
area := (end - start) * min(height[start], height[end])
|
||||
|
||||
// Futhermore, we can completely ignore A.
|
||||
//
|
||||
// The maximum area will either be the current `area`, or some other two
|
||||
// lines in the subset without A.
|
||||
var subset []int
|
||||
if height[start] < height[end] {
|
||||
subset = height[start+1:]
|
||||
} else {
|
||||
subset = height[:end]
|
||||
}
|
||||
|
||||
// We can now evaluate the problem space in the subset, and compute the
|
||||
// maximum area.
|
||||
return max(area, MaxArea(subset))
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package count_paths_that_can_form_a_palindrome_in_a_tree
|
||||
|
||||
func isPalindromable(s string) bool {
|
||||
set := map[rune]int{}
|
||||
|
||||
for _, b := range s {
|
||||
set[b]++
|
||||
}
|
||||
|
||||
singletons := 0
|
||||
for _, v := range set {
|
||||
switch v {
|
||||
case 1:
|
||||
singletons++
|
||||
case 2:
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return singletons < 2
|
||||
}
|
||||
|
||||
func CountPalindromePaths(parent []int, s string) int64 {
|
||||
return 0
|
||||
}
|
||||
53
pkg/questions/course_schedule/main.go
Normal file
53
pkg/questions/course_schedule/main.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package courseschedule
|
||||
|
||||
func visit(prereqs map[int][]int, temporary map[int]bool, permanent map[int]bool, class int) bool {
|
||||
if temporary[class] {
|
||||
return false
|
||||
}
|
||||
if permanent[class] {
|
||||
return true
|
||||
}
|
||||
|
||||
if _, ok := prereqs[class]; !ok {
|
||||
return true
|
||||
}
|
||||
|
||||
temporary[class] = true
|
||||
|
||||
for _, p := range prereqs[class] {
|
||||
if !visit(prereqs, temporary, permanent, p) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
permanent[class] = true
|
||||
temporary[class] = false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func canFinish(numCourses int, prerequisites [][]int) bool {
|
||||
prereqs := map[int][]int{}
|
||||
for _, p := range prerequisites {
|
||||
class, prerequisite := p[0], p[1]
|
||||
|
||||
if _, ok := prereqs[class]; !ok {
|
||||
prereqs[class] = []int{}
|
||||
}
|
||||
|
||||
prereqs[class] = append(prereqs[class], prerequisite)
|
||||
}
|
||||
|
||||
temporary, permanent := map[int]bool{}, map[int]bool{}
|
||||
for c := range prereqs {
|
||||
if permanent[c] {
|
||||
continue
|
||||
}
|
||||
|
||||
if !visit(prereqs, temporary, permanent, c) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
82
pkg/questions/find_median_from_data_stream/main.go
Normal file
82
pkg/questions/find_median_from_data_stream/main.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package findmedianfromdatastream
|
||||
|
||||
import "container/heap"
|
||||
|
||||
type IntHeap []int
|
||||
|
||||
func (h IntHeap) Len() int { return len(h) }
|
||||
func (h IntHeap) Less(i, j int) bool { return h[i] < h[j] }
|
||||
func (h IntHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
|
||||
|
||||
func (h *IntHeap) Push(x any) {
|
||||
*h = append(*h, x.(int))
|
||||
}
|
||||
|
||||
func (h IntHeap) Peek() int {
|
||||
return h[0]
|
||||
}
|
||||
|
||||
func (h *IntHeap) Pop() any {
|
||||
old := *h
|
||||
x := old[len(old)-1]
|
||||
*h = old[:len(old)-1]
|
||||
return x
|
||||
}
|
||||
|
||||
type MedianFinder struct {
|
||||
// Positive min-heap of top half of values.
|
||||
top *IntHeap
|
||||
// Negative min-heap of bottom half of values.
|
||||
bottom *IntHeap
|
||||
}
|
||||
|
||||
func Constructor() MedianFinder {
|
||||
result := MedianFinder{
|
||||
top: &IntHeap{},
|
||||
bottom: &IntHeap{},
|
||||
}
|
||||
|
||||
heap.Init(result.top)
|
||||
heap.Init(result.bottom)
|
||||
return result
|
||||
}
|
||||
|
||||
func (m *MedianFinder) AddNum(num int) {
|
||||
if m.bottom.Len() > m.top.Len() {
|
||||
if -m.bottom.Peek() <= num {
|
||||
heap.Push(m.top, num)
|
||||
} else {
|
||||
val := heap.Pop(m.bottom).(int)
|
||||
heap.Push(m.top, -val)
|
||||
heap.Push(m.bottom, -num)
|
||||
}
|
||||
} else if m.bottom.Len() < m.top.Len() {
|
||||
if m.top.Peek() >= num {
|
||||
heap.Push(m.bottom, -num)
|
||||
} else {
|
||||
val := heap.Pop(m.top).(int)
|
||||
heap.Push(m.bottom, -val)
|
||||
heap.Push(m.top, num)
|
||||
}
|
||||
} else {
|
||||
if m.top.Len() == 0 {
|
||||
heap.Push(m.top, num)
|
||||
} else {
|
||||
if median := m.FindMedian(); float64(num) > median {
|
||||
heap.Push(m.top, num)
|
||||
} else {
|
||||
heap.Push(m.bottom, -num)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MedianFinder) FindMedian() float64 {
|
||||
if m.bottom.Len() > m.top.Len() {
|
||||
return float64(-m.bottom.Peek())
|
||||
} else if m.bottom.Len() < m.top.Len() {
|
||||
return float64(m.top.Peek())
|
||||
} else {
|
||||
return float64(m.top.Peek()-m.bottom.Peek()) / 2.0
|
||||
}
|
||||
}
|
||||
13
pkg/questions/find_minimum_in_rotated_sorted_array/main.go
Normal file
13
pkg/questions/find_minimum_in_rotated_sorted_array/main.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package findminimuminrotatedsortedarray
|
||||
|
||||
func FindMin(nums []int) int {
|
||||
middle := len(nums) / 2
|
||||
|
||||
if nums[0] > nums[middle] {
|
||||
return FindMin(nums[1 : middle+1])
|
||||
} else if nums[middle] > nums[len(nums)-1] {
|
||||
return FindMin(nums[middle+1:])
|
||||
} else {
|
||||
return nums[0]
|
||||
}
|
||||
}
|
||||
41
pkg/questions/group_anagrams/main.go
Normal file
41
pkg/questions/group_anagrams/main.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package group_anagrams
|
||||
|
||||
import (
|
||||
"hash/maphash"
|
||||
"slices"
|
||||
)
|
||||
|
||||
func SortString(s string) string {
|
||||
runes := []rune(s)
|
||||
slices.Sort(runes)
|
||||
return string(runes)
|
||||
}
|
||||
|
||||
func AnagramHash(letters string) uint64 {
|
||||
var h maphash.Hash
|
||||
h.WriteString(SortString(letters))
|
||||
return h.Sum64()
|
||||
}
|
||||
|
||||
func GroupAnagrams(items []string) [][]string {
|
||||
anagrams := map[uint64][]string{}
|
||||
|
||||
for _, item := range items {
|
||||
hash := AnagramHash(item)
|
||||
similar, exists := anagrams[hash]
|
||||
|
||||
if exists {
|
||||
anagrams[hash] = append(similar, item)
|
||||
} else {
|
||||
anagrams[hash] = []string{item}
|
||||
}
|
||||
}
|
||||
|
||||
result := [][]string{}
|
||||
|
||||
for _, group := range anagrams {
|
||||
result = append(result, group)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
14
pkg/questions/group_anagrams/main_test.go
Normal file
14
pkg/questions/group_anagrams/main_test.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package group_anagrams_test
|
||||
|
||||
// import (
|
||||
// "testing"
|
||||
|
||||
// . "git.maximhutz.com/practice/pkg/group_anagrams"
|
||||
// "github.com/stretchr/testify/assert"
|
||||
// )
|
||||
|
||||
// func Test1(t *testing.T) {
|
||||
// assert.Equal(t,
|
||||
// [][]string{{"bat"}, {"nat", "tan"}, {"ate", "eat", "tea"}},
|
||||
// GroupAnagrams([]string{"eat", "tea", "tan", "ate", "nat", "bat"}))
|
||||
// }
|
||||
60
pkg/questions/largest_rectangle_in_histogram/main.go
Normal file
60
pkg/questions/largest_rectangle_in_histogram/main.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package largest_rectangle_in_histogram
|
||||
|
||||
type Box struct {
|
||||
Start int
|
||||
Height int
|
||||
}
|
||||
|
||||
// Calculates the size of the box, from its starting point upto (and NOT
|
||||
// including) a certain point.
|
||||
func (b Box) Size(upto int) int {
|
||||
return (upto - b.Start) * b.Height
|
||||
}
|
||||
|
||||
func LargestRectangleArea(heights []int) int {
|
||||
// This is a stack, containing all boxes that haven't been completed yet. Each
|
||||
// box contains two integers. The first is the starting index, and the second
|
||||
// is the height of the box.
|
||||
boxes := []Box{}
|
||||
// The accumulation of the biggest box so far.
|
||||
biggest := 0
|
||||
// Add a number that is guaranted to be lower than any other. This will pop out
|
||||
// any boxes left in the stack at the end of the program.
|
||||
heights = append(heights, -1)
|
||||
|
||||
for i, height := range heights {
|
||||
// This is the farthest index back where the eventual new box can start.
|
||||
// Everytime we pop a box off the top of the stack, this means every item
|
||||
// from the start of the box until now is > the current height. So, we can
|
||||
// extend that box at least that far back.
|
||||
farthest := i
|
||||
|
||||
for len(boxes) > 0 {
|
||||
top := boxes[len(boxes)-1]
|
||||
|
||||
// The boxes are implicitly ordered by height. When one gets the top box,
|
||||
// all below must have a <= height.
|
||||
//
|
||||
// If the very top box has a height <= to the current height, that means
|
||||
// all boxes left will carry over into the next iteration, so we can continue.
|
||||
if top.Height < height {
|
||||
break
|
||||
}
|
||||
|
||||
// Since this box is taller than the current height, it ends here.
|
||||
// We calculate its size, and accumulate it in the `biggest` variable.
|
||||
biggest = max(biggest, top.Size(i))
|
||||
|
||||
// Remove it from the stack.
|
||||
boxes = boxes[:len(boxes)-1]
|
||||
|
||||
// Push the starting point of the box farther back.
|
||||
farthest = top.Start
|
||||
}
|
||||
|
||||
// A box is always created for each new height.
|
||||
boxes = append(boxes, Box{Start: farthest, Height: height})
|
||||
}
|
||||
|
||||
return biggest
|
||||
}
|
||||
29
pkg/questions/largest_rectangle_in_histogram/main_test.go
Normal file
29
pkg/questions/largest_rectangle_in_histogram/main_test.go
Normal file
File diff suppressed because one or more lines are too long
28
pkg/questions/linked_list_cycle/main.go
Normal file
28
pkg/questions/linked_list_cycle/main.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package linked_list_cycle
|
||||
|
||||
type ListNode struct {
|
||||
Val int
|
||||
Next *ListNode
|
||||
}
|
||||
|
||||
func succeed(n *ListNode) *ListNode {
|
||||
if n == nil {
|
||||
return n
|
||||
} else {
|
||||
return n.Next
|
||||
}
|
||||
}
|
||||
|
||||
func HasCycle(head *ListNode) bool {
|
||||
one, two := head, succeed(head)
|
||||
|
||||
for one != nil && two != nil {
|
||||
if one == two {
|
||||
return true
|
||||
}
|
||||
|
||||
one, two = succeed(one), succeed(succeed(two))
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
86
pkg/questions/longest_consecutive_sequence/main.go
Normal file
86
pkg/questions/longest_consecutive_sequence/main.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package longest_consecutive_sequence
|
||||
|
||||
// type Node struct {
|
||||
// // The location of the parent node.
|
||||
// Parent *Node
|
||||
|
||||
// // The number of descendent nodes, including itself.
|
||||
// Children int
|
||||
// }
|
||||
|
||||
// func FindAncestor(n *Node) *Node {
|
||||
// ancestor := n
|
||||
|
||||
// for ancestor.Parent != nil {
|
||||
// ancestor = ancestor.Parent
|
||||
// }
|
||||
|
||||
// return ancestor
|
||||
// }
|
||||
|
||||
// func LongestConsecutive(nums []int) int {
|
||||
// nodes := map[int]*Node{}
|
||||
|
||||
// for _, num := range nums {
|
||||
// if _, exists := nodes[num]; exists {
|
||||
// continue
|
||||
// }
|
||||
|
||||
// node := &Node{Parent: nil, Children: 1}
|
||||
|
||||
// if lower, lower_exists := nodes[num-1]; lower_exists {
|
||||
// ancestor := FindAncestor(lower)
|
||||
// ancestor.Parent = node
|
||||
// node.Children += ancestor.Children
|
||||
// }
|
||||
|
||||
// if upper, lower_exists := nodes[num+1]; lower_exists {
|
||||
// ancestor := FindAncestor(upper)
|
||||
// ancestor.Parent = node
|
||||
// node.Children += ancestor.Children
|
||||
// }
|
||||
|
||||
// nodes[num] = node
|
||||
// }
|
||||
|
||||
// maximum := 0
|
||||
|
||||
// for _, node := range nodes {
|
||||
// maximum = max(maximum, node.Children)
|
||||
// }
|
||||
|
||||
// return maximum
|
||||
// }
|
||||
|
||||
func LongestConsecutive(nums []int) int {
|
||||
items := map[int]bool{}
|
||||
|
||||
for _, num := range nums {
|
||||
items[num] = true
|
||||
}
|
||||
|
||||
maximum := 0
|
||||
|
||||
for item, unused := range items {
|
||||
if !unused {
|
||||
continue
|
||||
}
|
||||
|
||||
items[item] = false
|
||||
sequence := 1
|
||||
|
||||
for i := item - 1; items[i]; i-- {
|
||||
items[i] = false
|
||||
sequence++
|
||||
}
|
||||
|
||||
for i := item + 1; items[i]; i++ {
|
||||
items[i] = false
|
||||
sequence++
|
||||
}
|
||||
|
||||
maximum = max(maximum, sequence)
|
||||
}
|
||||
|
||||
return maximum
|
||||
}
|
||||
32
pkg/questions/longest_consecutive_sequence/main_test.go
Normal file
32
pkg/questions/longest_consecutive_sequence/main_test.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package longest_consecutive_sequence_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.maximhutz.com/practice/pkg/longest_consecutive_sequence"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test1(t *testing.T) {
|
||||
assert.Equal(t, 4, longest_consecutive_sequence.LongestConsecutive([]int{100, 4, 200, 1, 3, 2}))
|
||||
}
|
||||
|
||||
func Test2(t *testing.T) {
|
||||
assert.Equal(t, 9, longest_consecutive_sequence.LongestConsecutive([]int{0, 3, 7, 2, 5, 8, 4, 6, 0, 1}))
|
||||
}
|
||||
|
||||
func Test3(t *testing.T) {
|
||||
assert.Equal(t, 3, longest_consecutive_sequence.LongestConsecutive([]int{1, 0, 1, 2}))
|
||||
}
|
||||
|
||||
func Test4(t *testing.T) {
|
||||
assert.Equal(t, 0, longest_consecutive_sequence.LongestConsecutive([]int{}))
|
||||
}
|
||||
|
||||
func Test5(t *testing.T) {
|
||||
assert.Equal(t, 7, longest_consecutive_sequence.LongestConsecutive([]int{1, 3, 5, 7, 2, 6, 4}))
|
||||
}
|
||||
|
||||
func Test6(t *testing.T) {
|
||||
assert.Equal(t, 7, longest_consecutive_sequence.LongestConsecutive([]int{1, 3, 5, 7, 2, 6, 4}))
|
||||
}
|
||||
63
pkg/questions/merge_k_sorted_lists/main.go
Normal file
63
pkg/questions/merge_k_sorted_lists/main.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package mergeksortedlists
|
||||
|
||||
import "container/heap"
|
||||
|
||||
type ListNode struct {
|
||||
Val int
|
||||
Next *ListNode
|
||||
}
|
||||
|
||||
type ListNodeHeap []*ListNode
|
||||
|
||||
func (l ListNodeHeap) Len() int {
|
||||
return len(l)
|
||||
}
|
||||
|
||||
func (l ListNodeHeap) Less(i int, j int) bool {
|
||||
if l[i] == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
if l[j] == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return l[i].Val < l[j].Val
|
||||
}
|
||||
|
||||
func (l *ListNodeHeap) Pop() (popped any) {
|
||||
*l, popped = (*l)[:len(*l)-1], (*l)[len(*l)-1]
|
||||
return
|
||||
}
|
||||
|
||||
func (l *ListNodeHeap) Push(x any) {
|
||||
*l = append(*l, x.(*ListNode))
|
||||
}
|
||||
|
||||
func (l ListNodeHeap) Swap(i int, j int) {
|
||||
l[i], l[j] = l[j], l[i]
|
||||
}
|
||||
|
||||
func MergeKLists(lists []*ListNode) *ListNode {
|
||||
hp := ListNodeHeap(lists)
|
||||
heap.Init(&hp)
|
||||
|
||||
sorted := ListNode{}
|
||||
head := &sorted
|
||||
|
||||
for len(hp) > 0 {
|
||||
min := heap.Pop(&hp).(*ListNode)
|
||||
if min == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
rest := min.Next
|
||||
|
||||
head.Next, head = min, min
|
||||
if rest != nil {
|
||||
heap.Push(&hp, rest)
|
||||
}
|
||||
}
|
||||
|
||||
return sorted.Next
|
||||
}
|
||||
33
pkg/questions/merge_two_sorted_lists/main.go
Normal file
33
pkg/questions/merge_two_sorted_lists/main.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package merge_two_sorted_lists
|
||||
|
||||
type ListNode struct {
|
||||
Val int
|
||||
Next *ListNode
|
||||
}
|
||||
|
||||
func MergeTwoLists(a *ListNode, b *ListNode) *ListNode {
|
||||
result := &ListNode{}
|
||||
head := result
|
||||
|
||||
for {
|
||||
if a == nil {
|
||||
if b == nil {
|
||||
break
|
||||
} else {
|
||||
head.Next, head, b = b, b, b.Next
|
||||
}
|
||||
} else {
|
||||
if b == nil {
|
||||
head.Next, head, a = a, a, a.Next
|
||||
} else {
|
||||
if a.Val < b.Val {
|
||||
head.Next, head, a = a, a, a.Next
|
||||
} else {
|
||||
head.Next, head, b = b, b, b.Next
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result.Next
|
||||
}
|
||||
95
pkg/questions/minimum_window_substring/main.go
Normal file
95
pkg/questions/minimum_window_substring/main.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package minimumwindowsubstring
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Set[T comparable] map[T]int
|
||||
|
||||
type Substring struct {
|
||||
Main string
|
||||
Left int
|
||||
Right int
|
||||
Set Set[byte]
|
||||
}
|
||||
|
||||
func Better(a, b string) string {
|
||||
if len(a) == 0 {
|
||||
return b
|
||||
} else if len(b) < len(a) {
|
||||
return b
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
func NewSubstring(s string) Substring {
|
||||
return Substring{s, 0, len(s) - 1, NewSet(s)}
|
||||
}
|
||||
|
||||
func (s Set[T]) SubsetOf(t Set[T]) bool {
|
||||
for k := range s {
|
||||
if s[k] > t[k] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func NewSet(t string) Set[byte] {
|
||||
set := Set[byte]{}
|
||||
for i := range t {
|
||||
set[t[i]]++
|
||||
}
|
||||
|
||||
return set
|
||||
}
|
||||
|
||||
func (s *Substring) CullLeft(t Substring) {
|
||||
for s.Set[s.Main[s.Left]] > t.Set[s.Main[s.Left]] {
|
||||
s.Set[s.Main[s.Left]]--
|
||||
s.Left++
|
||||
}
|
||||
|
||||
fmt.Println("CANNOT CULL", string(s.Main[s.Left]))
|
||||
}
|
||||
|
||||
func (s *Substring) IncRight() bool {
|
||||
if s.Right == len(s.Main)-1 {
|
||||
return false
|
||||
}
|
||||
|
||||
s.Right++
|
||||
s.Set[s.Main[s.Right]]++
|
||||
return true
|
||||
}
|
||||
|
||||
func (s Substring) String() string {
|
||||
return s.Main[s.Left : s.Right+1]
|
||||
}
|
||||
|
||||
func (s *Substring) CullRight(t Substring) {
|
||||
for s.Set[s.Main[s.Right]] > t.Set[s.Main[s.Right]] {
|
||||
s.Set[s.Main[s.Right]]--
|
||||
s.Right--
|
||||
}
|
||||
}
|
||||
|
||||
func minWindow(s string, t string) string {
|
||||
ss, tt := NewSubstring(s), NewSubstring(t)
|
||||
best_answer := ""
|
||||
|
||||
if !tt.Set.SubsetOf(ss.Set) {
|
||||
return best_answer
|
||||
}
|
||||
|
||||
ss.CullRight(tt)
|
||||
ss.CullLeft(tt)
|
||||
best_answer = Better(best_answer, ss.String())
|
||||
|
||||
for ss.IncRight() {
|
||||
ss.CullLeft(tt)
|
||||
best_answer = Better(best_answer, ss.String())
|
||||
}
|
||||
|
||||
return best_answer
|
||||
}
|
||||
105
pkg/questions/pacific_atlantic_water_flow/main.go
Normal file
105
pkg/questions/pacific_atlantic_water_flow/main.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package pacificatlanticwaterflow
|
||||
|
||||
type Position struct{ X, Y int }
|
||||
|
||||
func (p Position) Neighbors() []Position {
|
||||
return []Position{
|
||||
{p.X + 1, p.Y},
|
||||
{p.X - 1, p.Y},
|
||||
{p.X, p.Y + 1},
|
||||
{p.X, p.Y - 1},
|
||||
}
|
||||
}
|
||||
|
||||
func (p Position) ToList() []int {
|
||||
return []int{p.Y, p.X}
|
||||
}
|
||||
|
||||
type Board [][]int
|
||||
|
||||
func (b Board) Get(p Position) int {
|
||||
if b.OutOfBounds(p) {
|
||||
return -1
|
||||
}
|
||||
|
||||
return b[p.Y][p.X]
|
||||
}
|
||||
|
||||
func (b Board) Height() int { return len(b) }
|
||||
func (b Board) Width() int { return len(b[0]) }
|
||||
|
||||
func (b Board) OutOfBounds(p Position) bool {
|
||||
return p.Y < 0 || p.Y >= b.Height() || p.X < 0 || p.X >= b.Width()
|
||||
}
|
||||
|
||||
type Flow struct{ Pacific, Atlantic bool }
|
||||
|
||||
func (f *Flow) Merge(o Flow) {
|
||||
f.Atlantic = f.Atlantic || o.Atlantic
|
||||
f.Pacific = f.Pacific || o.Pacific
|
||||
}
|
||||
|
||||
func (f Flow) Both() bool {
|
||||
return f.Pacific && f.Atlantic
|
||||
}
|
||||
|
||||
func (b Board) GetFlow(p Position) Flow {
|
||||
return Flow{
|
||||
Atlantic: p.Y >= b.Height() || p.X >= b.Width(),
|
||||
Pacific: p.Y < 0 || p.X < 0,
|
||||
}
|
||||
}
|
||||
|
||||
func pacificAtlanticHelper(board Board, position Position, flows map[Position]Flow) Flow {
|
||||
if flow, ok := flows[position]; ok {
|
||||
return flow
|
||||
}
|
||||
|
||||
if board.OutOfBounds(position) {
|
||||
return board.GetFlow(position)
|
||||
}
|
||||
|
||||
flow := Flow{}
|
||||
|
||||
var top Position
|
||||
plateau := map[Position]bool{}
|
||||
unvisited := []Position{position}
|
||||
for len(unvisited) > 0 {
|
||||
top, unvisited = unvisited[len(unvisited)-1], unvisited[:len(unvisited)-1]
|
||||
|
||||
if board.Get(top) < board.Get(position) {
|
||||
flow.Merge(pacificAtlanticHelper(board, top, flows))
|
||||
} else if board.Get(top) == board.Get(position) {
|
||||
if _, ok := plateau[top]; !ok {
|
||||
plateau[top] = true
|
||||
unvisited = append(unvisited, top.Neighbors()...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for mem := range plateau {
|
||||
flows[mem] = flow
|
||||
}
|
||||
|
||||
return flow
|
||||
}
|
||||
|
||||
func PacificAtlantic(heights [][]int) [][]int {
|
||||
flows := map[Position]Flow{}
|
||||
board := Board(heights)
|
||||
|
||||
for y := range board.Height() {
|
||||
for x := range board.Width() {
|
||||
pacificAtlanticHelper(board, Position{x, y}, flows)
|
||||
}
|
||||
}
|
||||
|
||||
result := [][]int{}
|
||||
for position, flow := range flows {
|
||||
if flow.Both() {
|
||||
result = append(result, position.ToList())
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
62
pkg/questions/pacific_atlantic_water_flow/main_test.go
Normal file
62
pkg/questions/pacific_atlantic_water_flow/main_test.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package pacificatlanticwaterflow
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func sortResult(result [][]int) {
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
if result[i][0] != result[j][0] {
|
||||
return result[i][0] < result[j][0]
|
||||
}
|
||||
return result[i][1] < result[j][1]
|
||||
})
|
||||
}
|
||||
|
||||
func TestPacificAtlantic(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
heights [][]int
|
||||
expected [][]int
|
||||
}{
|
||||
{
|
||||
name: "5x5 grid",
|
||||
heights: [][]int{
|
||||
{1, 2, 2, 3, 5},
|
||||
{3, 2, 3, 4, 4},
|
||||
{2, 4, 5, 3, 1},
|
||||
{6, 7, 1, 4, 5},
|
||||
{5, 1, 1, 2, 4},
|
||||
},
|
||||
expected: [][]int{{0, 4}, {1, 3}, {1, 4}, {2, 2}, {3, 0}, {3, 1}, {4, 0}},
|
||||
},
|
||||
{
|
||||
name: "3x2 all ones",
|
||||
heights: [][]int{
|
||||
{1, 1},
|
||||
{1, 1},
|
||||
{1, 1},
|
||||
},
|
||||
expected: [][]int{{0, 0}, {0, 1}, {1, 0}, {1, 1}, {2, 0}, {2, 1}},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result := PacificAtlantic(tc.heights)
|
||||
sortResult(result)
|
||||
sortResult(tc.expected)
|
||||
|
||||
if len(result) != len(tc.expected) {
|
||||
t.Fatalf("expected %d results, got %d: %v", len(tc.expected), len(result), result)
|
||||
}
|
||||
|
||||
for i := range tc.expected {
|
||||
if result[i][0] != tc.expected[i][0] || result[i][1] != tc.expected[i][1] {
|
||||
t.Errorf("result[%d] = %v, expected %v", i, result[i], tc.expected[i])
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
25
pkg/questions/product_of_array_except_self/main.go
Normal file
25
pkg/questions/product_of_array_except_self/main.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package product_of_array_except_self
|
||||
|
||||
func ProductExceptSelf(nums []int) []int {
|
||||
result := []int{}
|
||||
|
||||
for range nums {
|
||||
result = append(result, 1)
|
||||
}
|
||||
|
||||
lower_sum := 1
|
||||
|
||||
for i := range len(nums) {
|
||||
result[i] *= lower_sum
|
||||
lower_sum *= nums[i]
|
||||
}
|
||||
|
||||
upper_sum := 1
|
||||
|
||||
for i := range len(nums) {
|
||||
result[len(nums)-1-i] *= upper_sum
|
||||
upper_sum *= nums[len(nums)-1-i]
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
16
pkg/questions/product_of_array_except_self/main_test.go
Normal file
16
pkg/questions/product_of_array_except_self/main_test.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package product_of_array_except_self_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.maximhutz.com/practice/pkg/product_of_array_except_self"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test1(t *testing.T) {
|
||||
assert.Equal(t, []int{24, 12, 8, 6}, product_of_array_except_self.ProductExceptSelf([]int{1, 2, 3, 4}))
|
||||
}
|
||||
|
||||
func Test2(t *testing.T) {
|
||||
assert.Equal(t, []int{0, 0, 9, 0, 0}, product_of_array_except_self.ProductExceptSelf([]int{-1, 1, 0, -3, 3}))
|
||||
}
|
||||
27
pkg/questions/remove_nth_node_from_end_of_list/main.go
Normal file
27
pkg/questions/remove_nth_node_from_end_of_list/main.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package removenthnodefromendoflist
|
||||
|
||||
type ListNode struct {
|
||||
Val int
|
||||
Next *ListNode
|
||||
}
|
||||
|
||||
func RemoveNthFromEnd(head *ListNode, n int) *ListNode {
|
||||
nodes := []*ListNode{}
|
||||
|
||||
for head != nil {
|
||||
nodes = append(nodes, head)
|
||||
head = head.Next
|
||||
}
|
||||
|
||||
if n == len(nodes) {
|
||||
return nodes[0].Next
|
||||
}
|
||||
|
||||
if n == 1 {
|
||||
nodes[len(nodes)-2].Next = nil
|
||||
return nodes[0]
|
||||
}
|
||||
|
||||
nodes[len(nodes)-(n+1)].Next = nodes[len(nodes)-(n-1)]
|
||||
return nodes[0]
|
||||
}
|
||||
34
pkg/questions/reorder_list/main.go
Normal file
34
pkg/questions/reorder_list/main.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package reorderlist
|
||||
|
||||
type ListNode struct {
|
||||
Val int
|
||||
Next *ListNode
|
||||
}
|
||||
|
||||
func ReorderList(head *ListNode) {
|
||||
nodes := []*ListNode{}
|
||||
for head != nil {
|
||||
nodes = append(nodes, head)
|
||||
head = head.Next
|
||||
}
|
||||
|
||||
start := 0
|
||||
end := len(nodes) - 1
|
||||
for {
|
||||
if start == end {
|
||||
nodes[start].Next = nil
|
||||
return
|
||||
}
|
||||
|
||||
nodes[start].Next = nodes[end]
|
||||
start++
|
||||
|
||||
if start == end {
|
||||
nodes[end].Next = nil
|
||||
return
|
||||
}
|
||||
|
||||
nodes[end].Next = nodes[start]
|
||||
end--
|
||||
}
|
||||
}
|
||||
19
pkg/questions/reverse_linked_list/main.go
Normal file
19
pkg/questions/reverse_linked_list/main.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package reverse_linked_list
|
||||
|
||||
type ListNode struct {
|
||||
Val int
|
||||
Next *ListNode
|
||||
}
|
||||
|
||||
func ReverseList(head *ListNode) *ListNode {
|
||||
var reversed *ListNode = nil
|
||||
current := head
|
||||
|
||||
for current != nil {
|
||||
next := current.Next
|
||||
current.Next = reversed
|
||||
reversed, current = current, next
|
||||
}
|
||||
|
||||
return reversed
|
||||
}
|
||||
30
pkg/questions/search_in_rotated_sorted_array/main.go
Normal file
30
pkg/questions/search_in_rotated_sorted_array/main.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package searchinrotatedsortedarray
|
||||
|
||||
func searchHelper(nums []int, target int, offset int) int {
|
||||
if len(nums) == 0 {
|
||||
return -1
|
||||
}
|
||||
|
||||
middle := len(nums) / 2
|
||||
if target == nums[middle] {
|
||||
return middle + offset
|
||||
}
|
||||
|
||||
if nums[0] > nums[middle] {
|
||||
if target >= nums[0] || target <= nums[middle] {
|
||||
return searchHelper(nums[:middle], target, offset)
|
||||
} else {
|
||||
return searchHelper(nums[middle+1:], target, offset+(middle+1))
|
||||
}
|
||||
} else {
|
||||
if target >= nums[0] && target <= nums[middle] {
|
||||
return searchHelper(nums[:middle], target, offset)
|
||||
} else {
|
||||
return searchHelper(nums[middle+1:], target, offset+(middle+1))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Search(nums []int, target int) int {
|
||||
return searchHelper(nums, target, 0)
|
||||
}
|
||||
41
pkg/questions/three_sum/main.go
Normal file
41
pkg/questions/three_sum/main.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package three_sum
|
||||
|
||||
import (
|
||||
"slices"
|
||||
)
|
||||
|
||||
func TwoSum(numbers []int, target int, solutions map[[3]int]bool) {
|
||||
start := 0
|
||||
end := len(numbers) - 1
|
||||
|
||||
for start < end {
|
||||
sum := numbers[start] + numbers[end]
|
||||
|
||||
if sum < target {
|
||||
start++
|
||||
} else if sum > target {
|
||||
end--
|
||||
} else {
|
||||
solutions[[3]int{-target, numbers[start], numbers[end]}] = true
|
||||
start++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ThreeSum(nums []int) [][]int {
|
||||
slices.Sort(nums)
|
||||
|
||||
solutions := map[[3]int]bool{}
|
||||
|
||||
for i := range nums {
|
||||
TwoSum(nums[i+1:], -nums[i], solutions)
|
||||
}
|
||||
|
||||
result := [][]int{}
|
||||
|
||||
for solution := range solutions {
|
||||
result = append(result, solution[:])
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
26
pkg/questions/three_sum/main_test.go
Normal file
26
pkg/questions/three_sum/main_test.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package three_sum_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.maximhutz.com/practice/pkg/three_sum"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test1(t *testing.T) {
|
||||
assert.ElementsMatch(t,
|
||||
[][]int{{-1, -1, 2}, {-1, 0, 1}},
|
||||
three_sum.ThreeSum([]int{-1, 0, 1, 2, -1, -4}))
|
||||
}
|
||||
|
||||
func Test2(t *testing.T) {
|
||||
assert.Equal(t,
|
||||
[][]int{},
|
||||
three_sum.ThreeSum([]int{0, 1, 1}))
|
||||
}
|
||||
|
||||
func Test3(t *testing.T) {
|
||||
assert.Equal(t,
|
||||
[][]int{{0, 0, 0}},
|
||||
three_sum.ThreeSum([]int{0, 0, 0}))
|
||||
}
|
||||
89
pkg/questions/top_k_frequent_elements/main.go
Normal file
89
pkg/questions/top_k_frequent_elements/main.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package top_k_frequent_elements
|
||||
|
||||
/// O(n*log(n))
|
||||
|
||||
// func ToMultiset(nums []int) map[int]int {
|
||||
// result := map[int]int{}
|
||||
|
||||
// for _, num := range nums {
|
||||
// result[num]++
|
||||
// }
|
||||
|
||||
// return result
|
||||
// }
|
||||
|
||||
// func ToEntries(multiset map[int]int) [][2]int {
|
||||
// result := [][2]int{}
|
||||
|
||||
// for num, amount := range multiset {
|
||||
// result = append(result, [2]int{num, amount})
|
||||
// }
|
||||
|
||||
// return result
|
||||
// }
|
||||
|
||||
// func ByDescendingAmount(a, b [2]int) int {
|
||||
// return b[1] - a[1]
|
||||
// }
|
||||
|
||||
// func GetNumbers(entries [][2]int) []int {
|
||||
// amounts := []int{}
|
||||
|
||||
// for _, entry := range entries {
|
||||
// amounts = append(amounts, entry[0])
|
||||
// }
|
||||
|
||||
// return amounts
|
||||
// }
|
||||
|
||||
// func TopKFrequent(nums []int, k int) []int {
|
||||
// multiset := ToMultiset(nums)
|
||||
// entries := ToEntries(multiset)
|
||||
|
||||
// slices.SortFunc(entries, ByDescendingAmount)
|
||||
// return GetNumbers(entries[0:k])
|
||||
// }
|
||||
|
||||
/// O(n)
|
||||
|
||||
func ToMultiset(nums []int) map[int]int {
|
||||
result := map[int]int{}
|
||||
|
||||
for _, num := range nums {
|
||||
result[num]++
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func TopKFrequent(nums []int, k int) []int {
|
||||
multiset := ToMultiset(nums)
|
||||
|
||||
// Bucket Sort.
|
||||
//
|
||||
// A multiset's frequency is always less then or equal to the length of the
|
||||
// original list. So, you can use bucket sort to sort the items in O(n).
|
||||
frequencies := make([][]int, len(nums))
|
||||
|
||||
for value, amount := range multiset {
|
||||
if frequencies[amount-1] == nil {
|
||||
frequencies[amount-1] = []int{}
|
||||
}
|
||||
|
||||
frequencies[amount-1] = append(frequencies[amount-1], value)
|
||||
}
|
||||
|
||||
top_frequencies := []int{}
|
||||
|
||||
for i := len(nums) - 1; i >= 0; i-- {
|
||||
for _, num := range frequencies[i] {
|
||||
top_frequencies = append(top_frequencies, num)
|
||||
|
||||
if len(top_frequencies) == k {
|
||||
return top_frequencies
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return top_frequencies
|
||||
}
|
||||
20
pkg/questions/top_k_frequent_elements/main_test.go
Normal file
20
pkg/questions/top_k_frequent_elements/main_test.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package top_k_frequent_elements_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.maximhutz.com/practice/pkg/top_k_frequent_elements"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test1(t *testing.T) {
|
||||
assert.Equal(t, []int{1, 2}, top_k_frequent_elements.TopKFrequent([]int{1, 1, 1, 2, 2, 3}, 2))
|
||||
}
|
||||
|
||||
func Test2(t *testing.T) {
|
||||
assert.Equal(t, []int{1}, top_k_frequent_elements.TopKFrequent([]int{1}, 1))
|
||||
}
|
||||
|
||||
func Test3(t *testing.T) {
|
||||
assert.Equal(t, []int{1, 4}, top_k_frequent_elements.TopKFrequent([]int{1, 4, 1, 4, 1, 4, 3, 1, 3, 4}, 2))
|
||||
}
|
||||
31
pkg/questions/trapping_rain_water/main.go
Normal file
31
pkg/questions/trapping_rain_water/main.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package trapping_rain_water
|
||||
|
||||
func Trap(heights []int) int {
|
||||
// Calculate area taken up by the boundary.
|
||||
boundary_area := 0
|
||||
for _, height := range heights {
|
||||
boundary_area += height
|
||||
}
|
||||
|
||||
// Calculate the total area taken up by the boundary and the water.
|
||||
total_area := 0
|
||||
left := 0
|
||||
left_height := 0
|
||||
right := len(heights) - 1
|
||||
right_height := 0
|
||||
|
||||
for left <= right {
|
||||
left_height = max(left_height, heights[left])
|
||||
right_height = max(right_height, heights[right])
|
||||
|
||||
if left_height < right_height {
|
||||
total_area += left_height
|
||||
left++
|
||||
} else {
|
||||
total_area += right_height
|
||||
right--
|
||||
}
|
||||
}
|
||||
|
||||
return total_area - boundary_area
|
||||
}
|
||||
31
pkg/questions/trapping_rain_water/main_test.go
Normal file
31
pkg/questions/trapping_rain_water/main_test.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package trapping_rain_water
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestTrap_Example1(t *testing.T) {
|
||||
height := []int{0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}
|
||||
expected := 6
|
||||
result := Trap(height)
|
||||
|
||||
assert.Equal(t, expected, result)
|
||||
}
|
||||
|
||||
func TestTrap_Example2(t *testing.T) {
|
||||
height := []int{4, 2, 0, 3, 2, 5}
|
||||
expected := 9
|
||||
result := Trap(height)
|
||||
|
||||
assert.Equal(t, expected, result)
|
||||
}
|
||||
|
||||
func TestTrap_Example3(t *testing.T) {
|
||||
height := []int{0}
|
||||
expected := 0
|
||||
result := Trap(height)
|
||||
|
||||
assert.Equal(t, expected, result)
|
||||
}
|
||||
49
pkg/questions/two_sum/main.go
Normal file
49
pkg/questions/two_sum/main.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package two_sum
|
||||
|
||||
import (
|
||||
"slices"
|
||||
)
|
||||
|
||||
type Index struct {
|
||||
Index int
|
||||
Value int
|
||||
}
|
||||
|
||||
func ByValue(a, b Index) int {
|
||||
return a.Value - b.Value
|
||||
}
|
||||
|
||||
func ToIndices(list []int) []Index {
|
||||
result := []Index{}
|
||||
|
||||
for index, value := range list {
|
||||
result = append(result, Index{index, value})
|
||||
}
|
||||
|
||||
slices.SortFunc(result, ByValue)
|
||||
return result
|
||||
}
|
||||
|
||||
// https://leetcode.com/problems/two-sum/description/
|
||||
|
||||
func TwoSum(nums []int, target int) []int {
|
||||
numbers := ToIndices(nums)
|
||||
lower, upper := 0, len(numbers)-1
|
||||
|
||||
for lower < upper {
|
||||
current_sum := numbers[lower].Value + numbers[upper].Value
|
||||
|
||||
if current_sum < target {
|
||||
lower++
|
||||
} else if current_sum > target {
|
||||
upper--
|
||||
} else {
|
||||
return []int{
|
||||
numbers[lower].Index,
|
||||
numbers[upper].Index,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
14
pkg/questions/two_sum/main_test.go
Normal file
14
pkg/questions/two_sum/main_test.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package two_sum_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.maximhutz.com/practice/pkg/two_sum"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestTwoSum(t *testing.T) {
|
||||
assert.Equal(t, two_sum.TwoSum([]int{2, 7, 11, 15}, 9), []int{0, 1})
|
||||
assert.Equal(t, two_sum.TwoSum([]int{3, 2, 4}, 6), []int{1, 2})
|
||||
assert.Equal(t, two_sum.TwoSum([]int{3, 3}, 6), []int{0, 1})
|
||||
}
|
||||
30
pkg/questions/valid_palindrome/main.go
Normal file
30
pkg/questions/valid_palindrome/main.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package valid_palindrome
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var notAlphanumeric = regexp.MustCompile(`[^a-zA-Z0-9]`)
|
||||
|
||||
func KeepAlphanumeric(text string) string {
|
||||
return notAlphanumeric.ReplaceAllString(text, "")
|
||||
}
|
||||
|
||||
func IsPalindrome(text string) bool {
|
||||
scrubbed := strings.ToLower(KeepAlphanumeric(text))
|
||||
|
||||
start := 0
|
||||
end := len(scrubbed) - 1
|
||||
|
||||
for start < end {
|
||||
if scrubbed[start] != scrubbed[end] {
|
||||
return false
|
||||
}
|
||||
|
||||
start++
|
||||
end--
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
14
pkg/questions/valid_palindrome/main_test.go
Normal file
14
pkg/questions/valid_palindrome/main_test.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package valid_palindrome_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.maximhutz.com/practice/pkg/valid_palindrome"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestTwoSum(t *testing.T) {
|
||||
assert.Equal(t, true, valid_palindrome.IsPalindrome("A man, a plan, a canal: Panama"))
|
||||
assert.Equal(t, false, valid_palindrome.IsPalindrome("race a car"))
|
||||
assert.Equal(t, true, valid_palindrome.IsPalindrome(" "))
|
||||
}
|
||||
46
pkg/questions/valid_sudoku/main.go
Normal file
46
pkg/questions/valid_sudoku/main.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package valid_sudoku
|
||||
|
||||
type Multiset map[byte]bool
|
||||
|
||||
func (m Multiset) Add(b byte) bool {
|
||||
if b == '.' {
|
||||
return true
|
||||
}
|
||||
|
||||
exists := m[b]
|
||||
m[b] = true
|
||||
return !exists
|
||||
}
|
||||
|
||||
func IsValidSudoku(board [][]byte) bool {
|
||||
for i := range 3 {
|
||||
for j := range 3 {
|
||||
box := Multiset{}
|
||||
|
||||
for x := range 3 {
|
||||
for y := range 3 {
|
||||
if !box.Add(board[3*j+y][3*i+x]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for i := range 9 {
|
||||
row := Multiset{}
|
||||
column := Multiset{}
|
||||
|
||||
for j := range 9 {
|
||||
if !row.Add(board[i][j]) {
|
||||
return false
|
||||
}
|
||||
|
||||
if !column.Add(board[j][i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
56
pkg/questions/valid_sudoku/main_test.go
Normal file
56
pkg/questions/valid_sudoku/main_test.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package valid_sudoku_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.maximhutz.com/practice/pkg/valid_sudoku"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test1(t *testing.T) {
|
||||
board := [][]byte{
|
||||
{'5', '3', '.', '.', '7', '.', '.', '.', '.'},
|
||||
{'6', '.', '.', '1', '9', '5', '.', '.', '.'},
|
||||
{'.', '9', '8', '.', '.', '.', '.', '6', '.'},
|
||||
{'8', '.', '.', '.', '6', '.', '.', '.', '3'},
|
||||
{'4', '.', '.', '8', '.', '3', '.', '.', '1'},
|
||||
{'7', '.', '.', '.', '2', '.', '.', '.', '6'},
|
||||
{'.', '6', '.', '.', '.', '.', '2', '8', '.'},
|
||||
{'.', '.', '.', '4', '1', '9', '.', '.', '5'},
|
||||
{'.', '.', '.', '.', '8', '.', '.', '7', '9'},
|
||||
}
|
||||
|
||||
assert.True(t, valid_sudoku.IsValidSudoku(board))
|
||||
}
|
||||
|
||||
func Test2(t *testing.T) {
|
||||
board := [][]byte{
|
||||
{'8', '3', '.', '.', '7', '.', '.', '.', '.'},
|
||||
{'6', '.', '.', '1', '9', '5', '.', '.', '.'},
|
||||
{'.', '9', '8', '.', '.', '.', '.', '6', '.'},
|
||||
{'8', '.', '.', '.', '6', '.', '.', '.', '3'},
|
||||
{'4', '.', '.', '8', '.', '3', '.', '.', '1'},
|
||||
{'7', '.', '.', '.', '2', '.', '.', '.', '6'},
|
||||
{'.', '6', '.', '.', '.', '.', '2', '8', '.'},
|
||||
{'.', '.', '.', '4', '1', '9', '.', '.', '5'},
|
||||
{'.', '.', '.', '.', '8', '.', '.', '7', '9'},
|
||||
}
|
||||
|
||||
assert.False(t, valid_sudoku.IsValidSudoku(board))
|
||||
}
|
||||
|
||||
func Test3(t *testing.T) {
|
||||
board := [][]byte{
|
||||
{'.', '.', '.', '.', '5', '.', '.', '1', '.'},
|
||||
{'.', '4', '.', '3', '.', '.', '.', '.', '.'},
|
||||
{'.', '.', '.', '.', '.', '3', '.', '.', '1'},
|
||||
{'8', '.', '.', '.', '.', '.', '.', '2', '.'},
|
||||
{'.', '.', '2', '.', '7', '.', '.', '.', '.'},
|
||||
{'.', '1', '5', '.', '.', '.', '.', '.', '.'},
|
||||
{'.', '.', '.', '.', '.', '2', '.', '.', '.'},
|
||||
{'.', '2', '.', '9', '.', '.', '.', '.', '.'},
|
||||
{'.', '.', '4', '.', '.', '.', '.', '.', '.'},
|
||||
}
|
||||
|
||||
assert.False(t, valid_sudoku.IsValidSudoku(board))
|
||||
}
|
||||
47
pkg/questions/wildcard_matching/main.go
Normal file
47
pkg/questions/wildcard_matching/main.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package wildcard_matching
|
||||
|
||||
var Cache = map[[2]string]bool{}
|
||||
|
||||
func MatchesCached(letters, pattern string) bool {
|
||||
key := [2]string{letters, pattern}
|
||||
|
||||
if matches, exists := Cache[key]; exists {
|
||||
return matches
|
||||
}
|
||||
|
||||
result := Matches(letters, pattern)
|
||||
Cache[key] = result
|
||||
return result
|
||||
}
|
||||
|
||||
func RemoveLeadingWildcards(pattern string) string {
|
||||
for i := 0; i < len(pattern); i++ {
|
||||
if pattern[i] != '*' {
|
||||
return pattern[i:]
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func Matches(letters string, pattern string) bool {
|
||||
if len(letters) == 0 && len(pattern) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
if len(pattern) != 0 && pattern[0] == '*' {
|
||||
for i := 0; i <= len(letters); i++ {
|
||||
if MatchesCached(letters[i:], RemoveLeadingWildcards(pattern)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
if len(pattern) != 0 && len(letters) != 0 && (pattern[0] == '?' || pattern[0] == letters[0]) {
|
||||
return MatchesCached(letters[1:], pattern[1:])
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
32
pkg/questions/wildcard_matching/main_test.go
Normal file
32
pkg/questions/wildcard_matching/main_test.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package wildcard_matching_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.maximhutz.com/practice/pkg/wildcard_matching"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestTwoSum1(t *testing.T) {
|
||||
assert.Equal(t, false, wildcard_matching.Matches("aa", "a"))
|
||||
}
|
||||
|
||||
func TestTwoSum2(t *testing.T) {
|
||||
assert.Equal(t, true, wildcard_matching.Matches("aa", "*"))
|
||||
}
|
||||
|
||||
func TestTwoSum3(t *testing.T) {
|
||||
assert.Equal(t, false, wildcard_matching.Matches("cb", "?a"))
|
||||
}
|
||||
|
||||
func TestTwoSum4(t *testing.T) {
|
||||
assert.Equal(t, true, wildcard_matching.Matches("banana", "**********"))
|
||||
}
|
||||
|
||||
func TestTwoSum5(t *testing.T) {
|
||||
assert.Equal(t, true, wildcard_matching.Matches("", "******"))
|
||||
}
|
||||
|
||||
func TestTwoSum6(t *testing.T) {
|
||||
assert.Equal(t, false, wildcard_matching.Matches("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab", "*******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************a"))
|
||||
}
|
||||
116
pkg/questions/word_search_ii/main.go
Normal file
116
pkg/questions/word_search_ii/main.go
Normal file
@@ -0,0 +1,116 @@
|
||||
package wordsearchii
|
||||
|
||||
type State struct {
|
||||
X, Y int
|
||||
Previous *State
|
||||
}
|
||||
|
||||
func (s *State) Visited(x, y int) bool {
|
||||
if s == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if s.X == x && s.Y == y {
|
||||
return true
|
||||
}
|
||||
|
||||
return s.Previous.Visited(x, y)
|
||||
}
|
||||
|
||||
type Trie struct {
|
||||
Children map[byte]*Trie
|
||||
States []*State
|
||||
}
|
||||
|
||||
func NewTrie(board [][]byte) *Trie {
|
||||
trie := &Trie{
|
||||
Children: map[byte]*Trie{},
|
||||
States: []*State{},
|
||||
}
|
||||
|
||||
for x := range board {
|
||||
for y := range board[x] {
|
||||
if _, ok := trie.Children[board[x][y]]; !ok {
|
||||
trie.Children[board[x][y]] = &Trie{
|
||||
Children: map[byte]*Trie{},
|
||||
States: []*State{},
|
||||
}
|
||||
}
|
||||
|
||||
trie.Children[board[x][y]].States = append(trie.Children[board[x][y]].States, &State{
|
||||
X: x,
|
||||
Y: y,
|
||||
Previous: nil,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return trie
|
||||
}
|
||||
|
||||
var CardinalDirections = [][2]int{
|
||||
{-1, 0},
|
||||
{1, 0},
|
||||
{0, -1},
|
||||
{0, 1},
|
||||
}
|
||||
|
||||
func (t *Trie) Explore(board [][]byte, ch byte) *Trie {
|
||||
child := &Trie{
|
||||
Children: map[byte]*Trie{},
|
||||
States: []*State{},
|
||||
}
|
||||
|
||||
for _, state := range t.States {
|
||||
for _, direction := range CardinalDirections {
|
||||
xNew, yNew := state.X+direction[0], state.Y+direction[1]
|
||||
|
||||
if xNew < 0 || xNew >= len(board) || yNew < 0 || yNew >= len(board[xNew]) {
|
||||
continue
|
||||
}
|
||||
|
||||
if state.Visited(xNew, yNew) {
|
||||
continue
|
||||
}
|
||||
|
||||
if ch != board[xNew][yNew] {
|
||||
continue
|
||||
}
|
||||
|
||||
child.States = append(child.States, &State{
|
||||
X: xNew,
|
||||
Y: yNew,
|
||||
Previous: state,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
t.Children[ch] = child
|
||||
return child
|
||||
}
|
||||
|
||||
func (t *Trie) FindWord(board [][]byte, word string) bool {
|
||||
if len(word) == 0 {
|
||||
return len(t.States) > 0
|
||||
}
|
||||
|
||||
child, ok := t.Children[word[0]]
|
||||
if !ok {
|
||||
child = t.Explore(board, word[0])
|
||||
}
|
||||
|
||||
return child.FindWord(board, word[1:])
|
||||
}
|
||||
|
||||
func FindWords(board [][]byte, words []string) []string {
|
||||
trie := NewTrie(board)
|
||||
found := []string{}
|
||||
|
||||
for _, word := range words {
|
||||
if trie.FindWord(board, word) {
|
||||
found = append(found, word)
|
||||
}
|
||||
}
|
||||
|
||||
return found
|
||||
}
|
||||
Reference in New Issue
Block a user