diff --git a/top-100-liked/12_test.go b/top-100-liked/12_test.go new file mode 100644 index 0000000..88f83ab --- /dev/null +++ b/top-100-liked/12_test.go @@ -0,0 +1,59 @@ +package top100liked + +import "testing" + +// https://leetcode.cn/problems/minimum-window-substring/?envType=study-plan-v2&envId=top-100-liked + +func minWindow(s string, t string) string { + if len(t) > len(s) { + return "" + } + need := make(map[byte]int) + for _, v := range []byte(t) { + need[v]++ + } + + window := make(map[byte]int) + valid := 0 + left := 0 + minLen := len(s) + 1 + start := 0 + + for right := 0; right < len(s); right++ { + ch := s[right] + if _, ok := need[ch]; ok { + window[ch]++ + if window[ch] == need[ch] { + valid++ + } + } + + for valid == len(need) { + if right-left+1 < minLen { + minLen = right - left + 1 + start = left + } + + d := s[left] + left++ + if _, ok := need[d]; ok { + if window[d] == need[d] { + valid-- + } + window[d]-- + } + } + } + + if minLen == len(s)+1 { + return "" + } + + return s[start : start+minLen] +} + +func TestS12(t *testing.T) { + println(minWindow("ADOBECODEBANC", "ABC")) + println(minWindow("a", "a")) + println(minWindow("a", "aa")) +} diff --git a/top-100-liked/13_1_test.go b/top-100-liked/13_1_test.go new file mode 100644 index 0000000..f47f224 --- /dev/null +++ b/top-100-liked/13_1_test.go @@ -0,0 +1,47 @@ +package top100liked + +import "testing" + +// https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/ + +// 贪心 +func maxProfit(prices []int) int { + minPrice := prices[0] // 历史最低买入价 + maxProfit := 0 + + for i := 1; i < len(prices); i++ { + // 如果今天卖,能赚多少? + profit := prices[i] - minPrice + maxProfit = max(maxProfit, profit) + + // 更新历史最低价 + minPrice = min(minPrice, prices[i]) + } + return maxProfit +} + +// 动态规划 +// dp[n][0] 第 n 天手中不持有股票时的最大利润 +// dp[n][1] 第 n 天手中持有股票时的最大利润 +// func maxProfit(prices []int) int { +// n := len(prices) +// if n == 0 { +// return 0 +// } + +// dp := make([][2]int, n) +// dp[0][0] = 0 +// dp[0][1] = -prices[0] + +// for i := 1; i < n; i++ { +// dp[i][0] = max(dp[i-1][0], dp[i-1][1]+prices[i]) +// dp[i][1] = max(dp[i-1][1], -prices[i]) +// } + +// return dp[n-1][0] +// } + +func TestS13_1(t *testing.T) { + println(maxProfit([]int{7, 1, 5, 3, 6, 4})) + println(maxProfit([]int{7, 6, 4, 3, 1})) +} diff --git a/top-100-liked/13_test.go b/top-100-liked/13_test.go new file mode 100644 index 0000000..7da46bc --- /dev/null +++ b/top-100-liked/13_test.go @@ -0,0 +1,43 @@ +package top100liked + +import "testing" + +// 爆内存 +// func maxSubArray(nums []int) int { +// l := len(nums) +// msa := make([][]int, l) +// for i := range msa { +// msa[i] = make([]int, l) +// } +// res := nums[0] +// for i, v := range nums { +// msa[i][i] = v +// res = max(res, v) +// } +// for i := range l { +// for j := i + 1; j < l; j++ { +// msa[i][j] = msa[i][j-1] + nums[j] +// res = max(res, msa[i][j]) +// } +// } +// return res +// } + +func maxSubArray(nums []int) int { + dp := make([]int, len(nums)) + dp[0] = nums[0] + maxSoFar := nums[0] + + for i := 1; i < len(nums); i++ { + dp[i] = max(nums[i], dp[i-1]+nums[i]) + maxSoFar = max(maxSoFar, dp[i]) + } + return maxSoFar +} + +func TestS13(t *testing.T) { + println(maxSubArray([]int{-2, 1, -3, 4, -1, 2, 1, -5, 4})) + println(maxSubArray([]int{1})) + println(maxSubArray([]int{5, 4, -1, 7, 8})) + println(maxSubArray([]int{-2, 1})) +} diff --git a/top-100-liked/14_test.go b/top-100-liked/14_test.go new file mode 100644 index 0000000..b50f286 --- /dev/null +++ b/top-100-liked/14_test.go @@ -0,0 +1,40 @@ +package top100liked + +import ( + "cmp" + "fmt" + "slices" + "testing" +) + +// https://leetcode.cn/problems/merge-intervals/?envType=study-plan-v2&envId=top-100-liked + +func merge(intervals [][]int) [][]int { + if len(intervals) <= 1 { + return intervals + } + + slices.SortFunc(intervals, func(a, b []int) int { + return cmp.Compare(a[0], b[0]) + }) + res := [][]int{} + cur := intervals[0] + for i := 1; i < len(intervals); i++ { + new := intervals[i] + // 判断是否重叠 + if cur[0] <= new[0] && new[0] <= cur[1] { + cur = []int{cur[0], max(cur[1], new[1])} + } else { + res = append(res, cur) + cur = new + } + } + res = append(res, cur) + return res +} + +func TestS14(t *testing.T) { + fmt.Printf("%+v\n", merge([][]int{{1, 3}, {2, 6}, {8, 10}, {15, 18}})) + fmt.Printf("%+v\n", merge([][]int{{1, 4}, {4, 5}})) + fmt.Printf("%+v\n", merge([][]int{{4, 7}, {1, 4}})) +} diff --git a/top-100-liked/15_test.go b/top-100-liked/15_test.go new file mode 100644 index 0000000..065163b --- /dev/null +++ b/top-100-liked/15_test.go @@ -0,0 +1,58 @@ +package top100liked + +import ( + "fmt" + "slices" + "testing" +) + +// https://leetcode.cn/problems/rotate-array/description/?envType=study-plan-v2&envId=top-100-liked + +func rotate(nums []int, k int) { + if k == 0 { + return + } + n := len(nums) + slices.Reverse(nums) + slices.Reverse(nums[:k%n]) + slices.Reverse(nums[k%n:]) +} + +// func rotate(nums []int, k int) { +// n := len(nums) +// k = k % n +// if k == 0 { +// return +// } + +// count := 0 // 已经处理了多少个元素 +// for start := 0; count < n; start++ { +// current := start +// prev := nums[start] // 暂存起点元素 + +// // 沿着环跳动 +// for { +// next := (current + k) % n +// // 把 prev 放到 next 位置,同时保存 next 原来的值作为新的 prev +// nums[next], prev = prev, nums[next] +// current = next +// count++ + +// if current == start { +// break // 回到起点,这条环走完了 +// } +// } +// } +// } + +func TestS15(t *testing.T) { + input := []int{1, 2, 3, 4, 5, 6, 7} + rotate(input, 3) + fmt.Printf("%+v\n", input) + input = []int{-1, -100, 3, 99} + rotate(input, 2) + fmt.Printf("%+v\n", input) + input = []int{-1} + rotate(input, 2) + fmt.Printf("%+v\n", input) +} diff --git a/top-100-liked/16_test.go b/top-100-liked/16_test.go new file mode 100644 index 0000000..ac3d11f --- /dev/null +++ b/top-100-liked/16_test.go @@ -0,0 +1,57 @@ +package top100liked + +import ( + "fmt" + "testing" +) + +// https://leetcode.cn/problems/product-of-array-except-self/?envType=study-plan-v2&envId=top-100-liked + +// func productExceptSelf(nums []int) []int { +// left := make([]int, len(nums)) +// right := make([]int, len(nums)) +// left[0] = nums[0] +// right[len(nums)-1] = nums[len(nums)-1] +// for i := 1; i < len(nums); i++ { +// left[i] = left[i-1] * nums[i] +// } +// for i := len(nums) - 2; i >= 0; i-- { +// right[i] = right[i+1] * nums[i] +// } +// res := []int{} +// for i := range nums { +// if i == 0 { +// res = append(res, right[1]) +// } else if i == len(nums)-1 { +// res = append(res, left[len(nums)-2]) +// } else { +// res = append(res, left[i-1]*right[i+1]) +// } +// } +// return res +// } + +func productExceptSelf(nums []int) []int { + n := len(nums) + answer := make([]int, n) + + // 第一遍:计算左边乘积,存入 answer + answer[0] = 1 + for i := 1; i < n; i++ { + answer[i] = answer[i-1] * nums[i-1] + } + + // 第二遍:从右向左,用 R 维护右边乘积 + R := 1 + for i := n - 1; i >= 0; i-- { + answer[i] = answer[i] * R // 左边积 × 右边积 + R = R * nums[i] // 更新右边积 + } + + return answer +} + +func TestS16(t *testing.T) { + fmt.Printf("%+v", productExceptSelf([]int{1, 2, 3, 4})) + fmt.Printf("%+v", productExceptSelf([]int{-1, 1, 0, -3, 3})) +} diff --git a/top-100-liked/17_test.go b/top-100-liked/17_test.go new file mode 100644 index 0000000..598e622 --- /dev/null +++ b/top-100-liked/17_test.go @@ -0,0 +1,31 @@ +package top100liked + +import "testing" + +// https://leetcode.cn/problems/first-missing-positive/description/?envType=study-plan-v2&envId=top-100-liked + +func firstMissingPositive(nums []int) int { + n := len(nums) + for i := range nums { + for nums[i] >= 1 && nums[i] <= n && nums[i] != i+1 { + if nums[i] != nums[nums[i]-1] { // 关键条件,否则会死循环 [1, 1] + nums[i], nums[nums[i]-1] = nums[nums[i]-1], nums[i] + } else { + break + } + } + } + for i, v := range nums { + if v != i+1 { + return i + 1 + } + } + return n + 1 +} + +func TestS17(t *testing.T) { + // println(firstMissingPositive([]int{1, 2, 0})) + // println(firstMissingPositive([]int{3, 4, -1, 1})) + // println(firstMissingPositive([]int{7, 8, 9, 11, 12})) + println(firstMissingPositive([]int{1, 1})) +}