diff --git a/go.mod b/go.mod index 0c65f5f3e..685ef07e7 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module awesome-golang-algorithm go 1.24 require ( + github.com/emirpasic/gods/v2 v2.0.0-alpha github.com/imroc/req/v3 v3.54.2 github.com/stretchr/testify v1.11.1 ) diff --git a/go.sum b/go.sum index 65e77a342..938e16551 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,8 @@ github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUS github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emirpasic/gods/v2 v2.0.0-alpha h1:dwFlh8pBg1VMOXWGipNMRt8v96dKAIvBehtCt6OtunU= +github.com/emirpasic/gods/v2 v2.0.0-alpha/go.mod h1:W0y4M2dtBB9U5z3YlghmpuUhiaZT2h6yoeE+C1sCp6A= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/icholy/digest v1.1.0 h1:HfGg9Irj7i+IX1o1QAmPfIBNu/Q5A5Tu3n/MED9k9H4= diff --git a/leetcode/3301-3400/3321.Find-X-Sum-of-All-K-Long-Subarrays-II/README.md b/leetcode/3301-3400/3321.Find-X-Sum-of-All-K-Long-Subarrays-II/README.md index a0d20fb01..d10b45bf2 100755 --- a/leetcode/3301-3400/3321.Find-X-Sum-of-All-K-Long-Subarrays-II/README.md +++ b/leetcode/3301-3400/3321.Find-X-Sum-of-All-K-Long-Subarrays-II/README.md @@ -1,28 +1,43 @@ # [3321.Find X-Sum of All K-Long Subarrays II][title] -> [!WARNING|style:flat] -> This question is temporarily unanswered if you have good ideas. Welcome to [Create Pull Request PR](https://github.com/kylesliu/awesome-golang-algorithm) - ## Description +You are given an array `nums` of `n` integers and two integers `k` and `x`. + +The **x-sum** of an array is calculated by the following procedure: + +- Count the occurrences of all elements in the array. +- Keep only the occurrences of the top `x` most frequent elements. If two elements have the same number of occurrences, the element with the **bigger** value is considered more frequent. +- Calculate the sum of the resulting array. + +**Note** that if an array has less than x distinct elements, its **x-sum** is the sum of the array. + +Return an integer array `answer` of length `n - k + 1` where `answer[i]` is the **x-sum** of the subarray `nums[i..i + k - 1]`. **Example 1:** ``` -Input: a = "11", b = "1" -Output: "100" -``` +Input: nums = [1,1,2,2,3,4,2,3], k = 6, x = 2 -## 题意 -> ... +Output: [6,10,12] -## 题解 +Explanation: -### 思路1 -> ... -Find X-Sum of All K-Long Subarrays II -```go +For subarray [1, 1, 2, 2, 3, 4], only elements 1 and 2 will be kept in the resulting array. Hence, answer[0] = 1 + 1 + 2 + 2. +For subarray [1, 2, 2, 3, 4, 2], only elements 2 and 4 will be kept in the resulting array. Hence, answer[1] = 2 + 2 + 2 + 4. Note that 4 is kept in the array since it is bigger than 3 and 1 which occur the same number of times. +For subarray [2, 2, 3, 4, 2, 3], only elements 2 and 3 are kept in the resulting array. Hence, answer[2] = 2 + 2 + 2 + 3 + 3. ``` +**Example 2:** + +``` +Input: nums = [3,8,7,8,7,5], k = 2, x = 2 + +Output: [11,15,15,15,12] + +Explanation: + +Since k == x, answer[i] is equal to the sum of the subarray nums[i..i + k - 1]. +``` ## 结语 diff --git a/leetcode/3301-3400/3321.Find-X-Sum-of-All-K-Long-Subarrays-II/Solution.go b/leetcode/3301-3400/3321.Find-X-Sum-of-All-K-Long-Subarrays-II/Solution.go index d115ccf5e..a43bf58c3 100644 --- a/leetcode/3301-3400/3321.Find-X-Sum-of-All-K-Long-Subarrays-II/Solution.go +++ b/leetcode/3301-3400/3321.Find-X-Sum-of-All-K-Long-Subarrays-II/Solution.go @@ -1,5 +1,107 @@ package Solution -func Solution(x bool) bool { - return x +import ( + "github.com/emirpasic/gods/v2/trees/redblacktree" +) + +func Solution(nums []int, k int, x int) []int64 { + helper := NewHelper(x) + ans := []int64{} + + for i := 0; i < len(nums); i++ { + helper.Insert(nums[i]) + if i >= k { + helper.Remove(nums[i-k]) + } + if i >= k-1 { + ans = append(ans, helper.Get()) + } + } + + return ans +} + +type Helper struct { + x int + result int64 + large *redblacktree.Tree[pair, struct{}] + small *redblacktree.Tree[pair, struct{}] + occ map[int]int +} + +type pair struct { + freq int + num int +} + +func pairComparator(a, b pair) int { + if a.freq != b.freq { + return a.freq - b.freq + } + return a.num - b.num +} + +func NewHelper(x int) *Helper { + return &Helper{ + x: x, + result: 0, + large: redblacktree.NewWith[pair, struct{}](pairComparator), + small: redblacktree.NewWith[pair, struct{}](pairComparator), + occ: make(map[int]int), + } +} + +func (h *Helper) Insert(num int) { + if h.occ[num] > 0 { + h.internalRemove(pair{freq: h.occ[num], num: num}) + } + h.occ[num]++ + h.internalInsert(pair{freq: h.occ[num], num: num}) +} + +func (h *Helper) Remove(num int) { + h.internalRemove(pair{freq: h.occ[num], num: num}) + h.occ[num]-- + if h.occ[num] > 0 { + h.internalInsert(pair{freq: h.occ[num], num: num}) + } +} + +func (h *Helper) Get() int64 { + return h.result +} + +func (h *Helper) internalInsert(p pair) { + if h.large.Size() < h.x { + h.result += int64(p.freq) * int64(p.num) + h.large.Put(p, struct{}{}) + } else { + minLarge := h.large.Left().Key + if pairComparator(p, minLarge) > 0 { + h.result += int64(p.freq) * int64(p.num) + h.large.Put(p, struct{}{}) + toRemove := h.large.Left().Key + h.result -= int64(toRemove.freq) * int64(toRemove.num) + h.large.Remove(toRemove) + h.small.Put(toRemove, struct{}{}) + } else { + h.small.Put(p, struct{}{}) + } + } +} + +func (h *Helper) internalRemove(p pair) { + if _, found := h.large.Get(p); found { + h.result -= int64(p.freq) * int64(p.num) + h.large.Remove(p) + + if h.small.Size() > 0 { + maxSmall := h.small.Right().Key + h.result += int64(maxSmall.freq) * int64(maxSmall.num) + h.small.Remove(maxSmall) + h.large.Put(maxSmall, struct{}{}) + } + } else if _, found := h.small.Get(p); found { + h.small.Remove(p) + } } diff --git a/leetcode/3301-3400/3321.Find-X-Sum-of-All-K-Long-Subarrays-II/Solution_test.go b/leetcode/3301-3400/3321.Find-X-Sum-of-All-K-Long-Subarrays-II/Solution_test.go index 14ff50eb4..0bb36c71f 100644 --- a/leetcode/3301-3400/3321.Find-X-Sum-of-All-K-Long-Subarrays-II/Solution_test.go +++ b/leetcode/3301-3400/3321.Find-X-Sum-of-All-K-Long-Subarrays-II/Solution_test.go @@ -10,30 +10,30 @@ func TestSolution(t *testing.T) { // 测试用例 cases := []struct { name string - inputs bool - expect bool + inputs []int + k, x int + expect []int64 }{ - {"TestCase", true, true}, - {"TestCase", true, true}, - {"TestCase", false, false}, + {"TestCase1", []int{1, 1, 2, 2, 3, 4, 2, 3}, 6, 2, []int64{6, 10, 12}}, + {"TestCase2", []int{3, 8, 7, 8, 7, 5}, 2, 2, []int64{11, 15, 15, 15, 12}}, } // 开始测试 for i, c := range cases { t.Run(c.name+" "+strconv.Itoa(i), func(t *testing.T) { - got := Solution(c.inputs) + got := Solution(c.inputs, c.k, c.x) if !reflect.DeepEqual(got, c.expect) { - t.Fatalf("expected: %v, but got: %v, with inputs: %v", - c.expect, got, c.inputs) + t.Fatalf("expected: %v, but got: %v, with inputs: %v %v %v", + c.expect, got, c.inputs, c.k, c.x) } }) } } -// 压力测试 +// 压力测试 func BenchmarkSolution(b *testing.B) { } -// 使用案列 +// 使用案列 func ExampleSolution() { }