diff --git a/solutions/0/q97/solution.go b/solutions/0/q97/solution.go new file mode 100644 index 0000000..d9ea20d --- /dev/null +++ b/solutions/0/q97/solution.go @@ -0,0 +1,32 @@ +package q97 + +func isInterleave(s1 string, s2 string, s3 string) bool { + if len(s1)+len(s2) != len(s3) { + return false + } + + possible := make([][]bool, len(s1)+1) + for i := range possible { + possible[i] = make([]bool, len(s2)+1) + } + possible[0][0] = true + + for tLen := 1; tLen <= len(s3); tLen++ { + c := s3[tLen-1] + for len1 := max(0, tLen-len(s2)); len1 <= min(len(s1), tLen); len1++ { + len2 := tLen - len1 + + if len1 > 0 && s1[len1-1] == c && possible[len1-1][len2] { + possible[len1][len2] = true + continue + } + if len2 > 0 && s2[len2-1] == c && possible[len1][len2-1] { + possible[len1][len2] = true + } + } + } + + return possible[len(s1)][len(s2)] +} + +var _ = isInterleave diff --git a/solutions/1/q150/solution.go b/solutions/1/q150/solution.go index 6eeeb7f..ce09cab 100644 --- a/solutions/1/q150/solution.go +++ b/solutions/1/q150/solution.go @@ -1,24 +1,29 @@ package q150 -func twoSum(numbers []int, target int) []int { - l, r := 0, len(numbers)-1 +import "strconv" - for l < r { - for numbers[r]+numbers[l] > target { - r-- - } - if numbers[r]+numbers[l] == target { - return []int{l + 1, r + 1} - } +func evalRPN(tokens []string) int { + stack := make([]int, 0, len(tokens)/2) + for _, s := range tokens { + height := len(stack) - for numbers[r]+numbers[l] < target { - l++ - } - if numbers[r]+numbers[l] == target { - return []int{l + 1, r + 1} + switch s { + case "+": + stack[height-2] += stack[height-1] + case "-": + stack[height-2] -= stack[height-1] + case "*": + stack[height-2] *= stack[height-1] + case "/": + stack[height-2] /= stack[height-1] + default: + num, _ := strconv.ParseInt(s, 10, strconv.IntSize) + stack = append(stack, int(num)) + continue } + stack = stack[:height-1] } - return []int{} // impossible + return stack[0] } -var _ = twoSum +var _ = evalRPN diff --git a/solutions/1/q167/solution.go b/solutions/1/q167/solution.go new file mode 100644 index 0000000..c3dffda --- /dev/null +++ b/solutions/1/q167/solution.go @@ -0,0 +1,24 @@ +package q167 + +func twoSum(numbers []int, target int) []int { + l, r := 0, len(numbers)-1 + + for l < r { + for numbers[r]+numbers[l] > target { + r-- + } + if numbers[r]+numbers[l] == target { + return []int{l + 1, r + 1} + } + + for numbers[r]+numbers[l] < target { + l++ + } + if numbers[r]+numbers[l] == target { + return []int{l + 1, r + 1} + } + } + return []int{} // impossible +} + +var _ = twoSum diff --git a/solutions/10/q1071/solution.go b/solutions/10/q1071/solution.go new file mode 100644 index 0000000..bb3a9b9 --- /dev/null +++ b/solutions/10/q1071/solution.go @@ -0,0 +1,28 @@ +package q1071 + +func isRepeatOf(segment, str string) bool { + if len(segment) > len(str) || len(segment) == 0 || len(str)%len(segment) != 0 { + return false + } + for len(str) > 0 { + if str[:len(segment)] != segment { + return false + } + str = str[len(segment):] + } + return true +} + +func gcdOfStrings(str1 string, str2 string) string { + if len(str1) > len(str2) { + str1, str2 = str2, str1 + } + for l := len(str1); l > 0; l-- { + if isRepeatOf(str1[:l], str1) && isRepeatOf(str1[:l], str2) { + return str1[:l] + } + } + return "" +} + +var _ = gcdOfStrings diff --git a/solutions/11/q1137/solution.go b/solutions/11/q1137/solution.go new file mode 100644 index 0000000..87cbdf9 --- /dev/null +++ b/solutions/11/q1137/solution.go @@ -0,0 +1,14 @@ +package q1137 + +func tribonacci(n int) int { + a := [3]int{0, 1, 1} + if n < 3 { + return a[n] + } + for range n - 3 + 1 { + a = [3]int{a[1], a[2], a[0] + a[1] + a[2]} + } + return a[2] +} + +var _ = tribonacci diff --git a/solutions/12/q1207/solution.go b/solutions/12/q1207/solution.go new file mode 100644 index 0000000..ddb5eec --- /dev/null +++ b/solutions/12/q1207/solution.go @@ -0,0 +1,25 @@ +package q1207 + +import "slices" + +type void struct{} + +func uniqueOccurrences(arr []int) bool { + slices.Sort(arr) + seen := map[int]void{} + + for i := 0; i < len(arr); { + c := arr[i] + count := 0 + for ; i < len(arr) && arr[i] == c; i++ { + count++ + } + if _, ok := seen[count]; ok { + return false + } + seen[count] = void{} + } + return true +} + +var _ = uniqueOccurrences diff --git a/solutions/13/q1365/solution.go b/solutions/13/q1365/solution.go new file mode 100644 index 0000000..cff957e --- /dev/null +++ b/solutions/13/q1365/solution.go @@ -0,0 +1,27 @@ +package q1365 + +import "slices" + +func smallerNumbersThanCurrent(nums []int) []int { + buf := make([]int, 2*len(nums)) + + positions := buf[0:len(nums)] + for i := range positions { + positions[i] = i + } + slices.SortFunc(positions, func(a, b int) int { return nums[a] - nums[b] }) + + nLesser := buf[len(nums):] + last := -1 + for i, p := range positions { + if nums[p] == last { + nLesser[p] = nLesser[positions[i-1]] + } else { + last = nums[p] + nLesser[p] = i + } + } + return nLesser +} + +var _ = smallerNumbersThanCurrent diff --git a/solutions/14/q1431/solution.go b/solutions/14/q1431/solution.go new file mode 100644 index 0000000..92b217a --- /dev/null +++ b/solutions/14/q1431/solution.go @@ -0,0 +1,16 @@ +package q1431 + +import "slices" + +func kidsWithCandies(candies []int, extraCandies int) []bool { + ret := make([]bool, len(candies)) + maxC := slices.Max(candies) + for i, c := range candies { + if c+extraCandies >= maxC { + ret[i] = true + } + } + return ret +} + +var _ = kidsWithCandies diff --git a/solutions/14/q1458/solution.go b/solutions/14/q1458/solution.go new file mode 100644 index 0000000..bc88f4b --- /dev/null +++ b/solutions/14/q1458/solution.go @@ -0,0 +1,38 @@ +package q1458 + +import "math" + +func maxDotProduct(nums1 []int, nums2 []int) int { + board := make([][]int, len(nums1)) + boardBuf := make([]int, len(nums1)*len(nums2)) + for i := range board { + board[i] = boardBuf[i*len(nums2) : (i+1)*len(nums2)] + } + maxSingle := math.MinInt + + for i1 := range nums1 { + for i2 := range nums2 { + prod := nums1[i1] * nums2[i2] + maxSingle = max(maxSingle, prod) + + if i1 > 0 && i2 > 0 { + prod += board[i1-1][i2-1] + } + board[i1][i2] = max(0, prod) + + if i2 > 0 { + board[i1][i2] = max(board[i1][i2-1], board[i1][i2]) + } + if i1 > 0 { + board[i1][i2] = max(board[i1-1][i2], board[i1][i2]) + } + } + } + + if maxSingle <= 0 { + return maxSingle + } + return board[len(nums1)-1][len(nums2)-1] +} + +var _ = maxDotProduct diff --git a/solutions/14/q1470/solution.go b/solutions/14/q1470/solution.go new file mode 100644 index 0000000..d991f04 --- /dev/null +++ b/solutions/14/q1470/solution.go @@ -0,0 +1,14 @@ +package q1470 + +func shuffle(nums []int, n int) []int { + ret := make([]int, n*2) + for i, num := range nums[:n] { + ret[i*2] = num + } + for i, num := range nums[n : n*2] { + ret[i*2+1] = num + } + return ret +} + +var _ = shuffle diff --git a/solutions/17/q1732/solution.go b/solutions/17/q1732/solution.go new file mode 100644 index 0000000..a5232be --- /dev/null +++ b/solutions/17/q1732/solution.go @@ -0,0 +1,13 @@ +package q1732 + +func largestAltitude(gain []int) int { + alt := 0 + max_ := 0 + for _, g := range gain { + alt += g + max_ = max(alt, max_) + } + return max_ +} + +var _ = largestAltitude diff --git a/solutions/17/q1768/solution.go b/solutions/17/q1768/solution.go new file mode 100644 index 0000000..a21d28a --- /dev/null +++ b/solutions/17/q1768/solution.go @@ -0,0 +1,19 @@ +package q1768 + +import "strings" + +func mergeAlternately(word1 string, word2 string) string { + builder := strings.Builder{} + for i := range max(len(word1), len(word2)) { + if i < len(word1) { + builder.WriteByte(word1[i]) + } + if i < len(word2) { + builder.WriteByte(word2[i]) + } + } + + return builder.String() +} + +var _ = mergeAlternately diff --git a/solutions/19/q1929/solution.go b/solutions/19/q1929/solution.go new file mode 100644 index 0000000..56bc69f --- /dev/null +++ b/solutions/19/q1929/solution.go @@ -0,0 +1,7 @@ +package q1929 + +func getConcatenation(nums []int) []int { + return append(nums, nums...) +} + +var _ = getConcatenation diff --git a/solutions/2/q206/solution.go b/solutions/2/q206/solution.go new file mode 100644 index 0000000..b6001b8 --- /dev/null +++ b/solutions/2/q206/solution.go @@ -0,0 +1,18 @@ +package q206 + +type ListNode struct { + Val int + Next *ListNode +} + +func reverseList(head *ListNode) *ListNode { + var prev, current *ListNode = nil, head + for current != nil { + next := current.Next + current.Next = prev + prev, current = current, next + } + return prev +} + +var _ = reverseList diff --git a/solutions/2/q283/solution.go b/solutions/2/q283/solution.go new file mode 100644 index 0000000..a8f1268 --- /dev/null +++ b/solutions/2/q283/solution.go @@ -0,0 +1,17 @@ +package q283 + +func moveZeroes(nums []int) { + p := 0 + for i := range nums { + if nums[i] == 0 { + continue + } + nums[p] = nums[i] + p++ + } + for i := p; i < len(nums); i++ { + nums[i] = 0 + } +} + +var _ = moveZeroes diff --git a/solutions/22/q2215/solution.go b/solutions/22/q2215/solution.go new file mode 100644 index 0000000..50b96aa --- /dev/null +++ b/solutions/22/q2215/solution.go @@ -0,0 +1,42 @@ +package q2215 + +import "slices" + +func skip(nums []int, i int) int { + if i < len(nums) { + for c := nums[i]; i < len(nums) && nums[i] == c; i++ { + } + } + return i +} + +func findDifference(nums1 []int, nums2 []int) [][]int { + slices.Sort(nums1) + slices.Sort(nums2) + d1 := []int{} + d2 := []int{} + + i1, i2 := 0, 0 + for i1 < len(nums1) || i2 < len(nums2) { + // num2[i2] is unique + if i1 == len(nums1) || i2 < len(nums2) && nums2[i2] < nums1[i1] { + d2 = append(d2, nums2[i2]) + i2 = skip(nums2, i2) + continue + } + + // num1[i1] is unique + if i2 == len(nums2) || i1 < len(nums1) && nums1[i1] < nums2[i2] { + d1 = append(d1, nums1[i1]) + i1 = skip(nums1, i1) + continue + } + + i1 = skip(nums1, i1) + i2 = skip(nums2, i2) + } + + return [][]int{d1, d2} +} + +var _ = findDifference diff --git a/solutions/3/q338/solution.go b/solutions/3/q338/solution.go new file mode 100644 index 0000000..cba325d --- /dev/null +++ b/solutions/3/q338/solution.go @@ -0,0 +1,11 @@ +package q338 + +func countBits(n int) []int { + ret := make([]int, n+1) + for i := 1; i <= n; i++ { + ret[i] = ret[i>>1] + i%2 + } + return ret +} + +var _ = countBits diff --git a/solutions/3/q345/solution.go b/solutions/3/q345/solution.go new file mode 100644 index 0000000..3f63373 --- /dev/null +++ b/solutions/3/q345/solution.go @@ -0,0 +1,31 @@ +package q345 + +func isVowel(b byte) bool { + switch b { + case 'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U': + return true + } + return false +} + +func reverseVowels(s string) string { + edit := []byte(s) + + l, r := 0, len(edit)-1 + for l < r { + for l < r && !isVowel(edit[l]) { + l++ + } + for l < r && !isVowel(edit[r]) { + r-- + } + if l < r { + edit[l], edit[r] = edit[r], edit[l] + l++ + r-- + } + } + return string(edit) +} + +var _ = reverseVowels diff --git a/solutions/3/q374/solution.go b/solutions/3/q374/solution.go new file mode 100644 index 0000000..32f9708 --- /dev/null +++ b/solutions/3/q374/solution.go @@ -0,0 +1,22 @@ +package q374 + +func guess(num int) int { panic("stub") } + +func guessNumber(n int) int { + l, r := 1, n+1 + + for l < r { + m := (l + r) / 2 + switch guess(m) { + case -1: // too high + r = m + case 1: // too low + l = m + 1 + case 0: + return m + } + } + return -1 +} + +var _ = guessNumber diff --git a/solutions/4/q448/solution.go b/solutions/4/q448/solution.go new file mode 100644 index 0000000..1c043c0 --- /dev/null +++ b/solutions/4/q448/solution.go @@ -0,0 +1,22 @@ +package q448 + +func findDisappearedNumbers(nums []int) []int { + n := len(nums) + ret := make([]int, n) + for i := range ret { + ret[i] = i + 1 + } + for _, num := range nums { + ret[num-1] = -1 + } + p := 0 + for i := range ret { + if ret[i] != -1 { + ret[p] = ret[i] + p++ + } + } + return ret[:p] +} + +var _ = findDisappearedNumbers diff --git a/solutions/4/q485/solution.go b/solutions/4/q485/solution.go new file mode 100644 index 0000000..74eac37 --- /dev/null +++ b/solutions/4/q485/solution.go @@ -0,0 +1,18 @@ +package q485 + +func findMaxConsecutiveOnes(nums []int) int { + maxNum := 0 + cur := 0 + + for _, n := range nums { + if n == 1 { + cur++ + } else { + maxNum = max(maxNum, cur) + cur = 0 + } + } + return max(maxNum, cur) +} + +var _ = findMaxConsecutiveOnes diff --git a/solutions/6/q605/solution.go b/solutions/6/q605/solution.go new file mode 100644 index 0000000..81e1792 --- /dev/null +++ b/solutions/6/q605/solution.go @@ -0,0 +1,22 @@ +package q605 + +func canPlaceFlowers(flowerbed []int, n int) bool { + for i := 0; i < len(flowerbed); i++ { + if flowerbed[i] == 1 { + i++ + continue + } + + if (i == 0 || flowerbed[i-1] == 0) && (i == len(flowerbed)-1 || flowerbed[i+1] == 0) { + flowerbed[i] = 1 + i++ + n-- + if n <= 0 { + return true + } + } + } + return n == 0 +} + +var _ = canPlaceFlowers diff --git a/solutions/6/q643/solution.go b/solutions/6/q643/solution.go new file mode 100644 index 0000000..4bb7d0d --- /dev/null +++ b/solutions/6/q643/solution.go @@ -0,0 +1,23 @@ +package q643 + +import "math" + +func findMaxAverage(nums []int, k int) float64 { + var maxSum = math.MinInt + + sum := 0 + for i := range nums { + if i < k-1 { + sum += nums[i] + } else { + sum += nums[i] + if i >= k { + sum -= nums[i-k] + } + maxSum = max(maxSum, sum) + } + } + return float64(maxSum) / float64(k) +} + +var _ = findMaxAverage diff --git a/solutions/6/q645/solution.go b/solutions/6/q645/solution.go new file mode 100644 index 0000000..e214789 --- /dev/null +++ b/solutions/6/q645/solution.go @@ -0,0 +1,22 @@ +package q645 + +func findErrorNums(nums []int) []int { + var duplicated, missing int + seen := make([]bool, len(nums)) + + for _, n := range nums { + if seen[n-1] { + duplicated = n + } + seen[n-1] = true + } + for i, ok := range seen { + if !ok { + missing = i + 1 + break + } + } + return []int{duplicated, missing} +} + +var _ = findErrorNums diff --git a/solutions/7/q700/solution.go b/solutions/7/q700/solution.go new file mode 100644 index 0000000..7862ab2 --- /dev/null +++ b/solutions/7/q700/solution.go @@ -0,0 +1,24 @@ +package q700 + +type TreeNode struct { + Val int + Left *TreeNode + Right *TreeNode +} + +func searchBST(root *TreeNode, val int) *TreeNode { + if root == nil { + return nil + } + + switch { + case val == root.Val: + return root + case val > root.Val: + return searchBST(root.Right, val) + default: + return searchBST(root.Left, val) + } +} + +var _ = searchBST diff --git a/solutions/7/q724/solution.go b/solutions/7/q724/solution.go new file mode 100644 index 0000000..a47f413 --- /dev/null +++ b/solutions/7/q724/solution.go @@ -0,0 +1,21 @@ +package q724 + +func pivotIndex(nums []int) int { + sumL, sumR := 0, 0 + for _, n := range nums { + sumR += n + } + + for i := range nums { + sumR -= nums[i] + if i > 0 { + sumL += nums[i-1] + } + if sumL == sumR { + return i + } + } + return -1 +} + +var _ = pivotIndex diff --git a/solutions/7/q746/solution.go b/solutions/7/q746/solution.go new file mode 100644 index 0000000..5f39b3d --- /dev/null +++ b/solutions/7/q746/solution.go @@ -0,0 +1,11 @@ +package q746 + +func minCostClimbingStairs(cost []int) int { + minCost := make([]int, len(cost)+1) + for i := 2; i < len(minCost); i++ { + minCost[i] = min(minCost[i-2]+cost[i-2], minCost[i-1]+cost[i-1]) + } + return minCost[len(minCost)-1] +} + +var _ = minCostClimbingStairs diff --git a/solutions/8/q865/solution.go b/solutions/8/q865/solution.go new file mode 100644 index 0000000..5cc42c6 --- /dev/null +++ b/solutions/8/q865/solution.go @@ -0,0 +1,35 @@ +package q865 + +type TreeNode struct { + Val int + Left *TreeNode + Right *TreeNode +} + +func search(node *TreeNode, depth int) (*TreeNode, int) { + if node == nil { + return nil, 0 + } + + if node.Left == nil && node.Right == nil { + return node, depth + } + + ln, ld := search(node.Left, depth+1) + rn, rd := search(node.Right, depth+1) + switch { + case ld == rd: + return node, ld + case ld < rd: + return rn, rd + default: + return ln, ld + } +} + +func subtreeWithAllDeepest(root *TreeNode) *TreeNode { + node, _ := search(root, 1) + return node +} + +var _ = subtreeWithAllDeepest diff --git a/solutions/8/q872/solution.go b/solutions/8/q872/solution.go new file mode 100644 index 0000000..1b6862a --- /dev/null +++ b/solutions/8/q872/solution.go @@ -0,0 +1,34 @@ +package q872 + +import "slices" + +type TreeNode struct { + Val int + Left *TreeNode + Right *TreeNode +} + +func leafSeq(node *TreeNode, cache []int) []int { + if cache == nil { + cache = []int{} + } + leaf := true + if node.Left != nil { + leaf = false + cache = leafSeq(node.Left, cache) + } + if node.Right != nil { + leaf = false + cache = leafSeq(node.Right, cache) + } + if leaf { + cache = append(cache, node.Val) + } + return cache +} + +func leafSimilar(root1 *TreeNode, root2 *TreeNode) bool { + return slices.Equal(leafSeq(root1, nil), leafSeq(root2, nil)) +} + +var _ = leafSimilar diff --git a/solutions/9/q933/solution.go b/solutions/9/q933/solution.go new file mode 100644 index 0000000..b9ce339 --- /dev/null +++ b/solutions/9/q933/solution.go @@ -0,0 +1,46 @@ +package q933 + +type RecentCounter struct{ reqs []int } + +func Constructor() RecentCounter { + return RecentCounter{reqs: make([]int, 0, 1024)} +} + +func (c *RecentCounter) Ping(t int) int { + if cap(c.reqs) == len(c.reqs) { + alloc := make([]int, max(2048, 2*len(c.reqs))) + copy(alloc, c.reqs) + c.reqs = alloc[:len(c.reqs)] + } + + c.reqs = append(c.reqs, t) + + // Fast path + if len(c.reqs) < 8 || c.reqs[7] >= t-3000 { + i := 0 + for c.reqs[i] < t-3000 { + i++ + } + c.reqs = c.reqs[i:] + return len(c.reqs) + } + + // Use binary search to find the cut position + l, r := 0, len(c.reqs) + for l < r { + m := (l + r) / 2 + if c.reqs[m] < t-3000 { + l = m + 1 + } else { + r = m + } + } + c.reqs = c.reqs[l:] + return len(c.reqs) +} + +/** + * Your RecentCounter object will be instantiated and called as such: + * obj := Constructor(); + * param_1 := obj.Ping(t); + */