diff --git a/go.mod b/go.mod index a4a786998..31645c102 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module awesome-golang-algorithm go 1.25 require ( + github.com/emirpasic/gods/v2 v2.0.0-alpha github.com/imroc/req/v3 v3.56.0 github.com/stretchr/testify v1.11.1 ) diff --git a/go.sum b/go.sum index 300d3bc94..892219c19 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.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= @@ -12,8 +14,6 @@ github.com/icholy/digest v1.1.0 h1:HfGg9Irj7i+IX1o1QAmPfIBNu/Q5A5Tu3n/MED9k9H4= github.com/icholy/digest v1.1.0/go.mod h1:QNrsSGQ5v7v9cReDI0+eyjsXGUoRSUZQHeQ5C4XLa0Y= github.com/imroc/req/v3 v3.56.0 h1:t6YdqqerYBXhZ9+VjqsQs5wlKxdUNEvsgBhxWc1AEEo= github.com/imroc/req/v3 v3.56.0/go.mod h1:cUZSooE8hhzFNOrAbdxuemXDQxFXLQTnu3066jr7ZGk= -github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co= -github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0= github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk= github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -24,8 +24,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= -github.com/quic-go/quic-go v0.56.0 h1:q/TW+OLismmXAehgFLczhCDTYB3bFmua4D9lsNBWxvY= -github.com/quic-go/quic-go v0.56.0/go.mod h1:9gx5KsFQtw2oZ6GZTyh+7YEvOxWCL9WZAepnHxgAo6c= github.com/quic-go/quic-go v0.57.1 h1:25KAAR9QR8KZrCZRThWMKVAwGoiHIrNbT72ULHTuI10= github.com/quic-go/quic-go v0.57.1/go.mod h1:ly4QBAjHA2VhdnxhojRsCUOeJwKYg+taDlos92xb1+s= github.com/refraction-networking/utls v1.8.1 h1:yNY1kapmQU8JeM1sSw2H2asfTIwWxIkrMJI0pRUOCAo= @@ -38,8 +36,6 @@ github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZ github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= -golang.org/x/crypto v0.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU= -golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc= golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= 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() { }