Skip to content

Commit e0c1622

Browse files
authored
Merge pull request #1162 from 0xff-dev/2818
Add solution and test-cases for problem 2818
2 parents e96601e + ed5c176 commit e0c1622

File tree

3 files changed

+196
-11
lines changed

3 files changed

+196
-11
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# [2818.Apply Operations to Maximize Score][title]
2+
3+
## Description
4+
5+
You are given an array `nums` of `n` positive integers and an integer `k`.
6+
7+
Initially, you start with a score of `1`. You have to maximize your score by applying the following operation at most `k` times:
8+
9+
- Choose any **non-empty** subarray `nums[l, ..., r]` that you haven't chosen previously.
10+
- Choose an element `x` of `nums[l, ..., r]` with the highest **prime score**. If multiple such elements exist, choose the one with the smallest index.
11+
- Multiply your score by `x`.
12+
13+
Here, `nums[l, ..., r]` denotes the subarray of `nums` starting at index `l` and ending at the index `r`, both ends being inclusive.
14+
15+
The **prime score** of an integer `x` is equal to the number of distinct prime factors of x. For example, the prime score of `300` is `3` since `300 = 2 * 2 * 3 * 5 * 5`.
16+
17+
Return the **maximum possible score** after applying at most `k` operations.
18+
19+
Since the answer may be large, return it modulo `10^9 + 7`.
20+
21+
**Example 1:**
22+
23+
```
24+
Input: nums = [8,3,9,3,8], k = 2
25+
Output: 81
26+
Explanation: To get a score of 81, we can apply the following operations:
27+
- Choose subarray nums[2, ..., 2]. nums[2] is the only element in this subarray. Hence, we multiply the score by nums[2]. The score becomes 1 * 9 = 9.
28+
- Choose subarray nums[2, ..., 3]. Both nums[2] and nums[3] have a prime score of 1, but nums[2] has the smaller index. Hence, we multiply the score by nums[2]. The score becomes 9 * 9 = 81.
29+
It can be proven that 81 is the highest score one can obtain.
30+
```
31+
32+
**Example 2:**
33+
34+
```
35+
Input: nums = [19,12,14,6,10,18], k = 3
36+
Output: 4788
37+
Explanation: To get a score of 4788, we can apply the following operations:
38+
- Choose subarray nums[0, ..., 0]. nums[0] is the only element in this subarray. Hence, we multiply the score by nums[0]. The score becomes 1 * 19 = 19.
39+
- Choose subarray nums[5, ..., 5]. nums[5] is the only element in this subarray. Hence, we multiply the score by nums[5]. The score becomes 19 * 18 = 342.
40+
- Choose subarray nums[2, ..., 3]. Both nums[2] and nums[3] have a prime score of 2, but nums[2] has the smaller index. Hence, we multipy the score by nums[2]. The score becomes 342 * 14 = 4788.
41+
It can be proven that 4788 is the highest score one can obtain.
42+
```
43+
44+
## 结语
45+
46+
如果你同我一样热爱数据结构、算法、LeetCode,可以关注我 GitHub 上的 LeetCode 题解:[awesome-golang-algorithm][me]
47+
48+
[title]: https://leetcode.com/problems/apply-operations-to-maximize-score/
49+
[me]: https://github.com/kylesliu/awesome-golang-algorithm
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,141 @@
11
package Solution
22

3-
func Solution(x bool) bool {
3+
import (
4+
"container/heap"
5+
)
6+
7+
const mod2818 = 1_000_000_007
8+
9+
type Pair2818 struct {
10+
value int
11+
index int
12+
}
13+
14+
// PriorityQueue implements a priority queue for pairs based on value
15+
type PriorityQueue []Pair2818
16+
17+
func (pq PriorityQueue) Len() int {
18+
return len(pq)
19+
}
20+
21+
func (pq PriorityQueue) Less(i, j int) bool {
22+
return pq[i].value > pq[j].value // Max-heap based on value
23+
}
24+
25+
func (pq PriorityQueue) Swap(i, j int) {
26+
pq[i], pq[j] = pq[j], pq[i]
27+
}
28+
29+
func (pq *PriorityQueue) Push(x interface{}) {
30+
*pq = append(*pq, x.(Pair2818))
31+
}
32+
33+
func (pq *PriorityQueue) Pop() interface{} {
34+
old := *pq
35+
n := len(old)
36+
x := old[n-1]
37+
*pq = old[0 : n-1]
438
return x
539
}
40+
41+
// Helper function to compute the number of distinct prime factors
42+
func distinctPrimeFactors(x int) int {
43+
count := 0
44+
for i := 2; i*i <= x; i++ {
45+
if x%i == 0 {
46+
count++
47+
for x%i == 0 {
48+
x /= i
49+
}
50+
}
51+
}
52+
if x > 1 {
53+
count++ // If x is a prime number larger than sqrt(original x)
54+
}
55+
return count
56+
}
57+
58+
func Solution(nums []int, k int) int {
59+
n := len(nums)
60+
primeScores := make([]int, n)
61+
62+
for i := 0; i < n; i++ {
63+
primeScores[i] = distinctPrimeFactors(nums[i])
64+
}
65+
66+
nextDominant := make([]int, n)
67+
prevDominant := make([]int, n)
68+
for i := 0; i < n; i++ {
69+
nextDominant[i] = n
70+
prevDominant[i] = -1
71+
}
72+
73+
stack := []int{}
74+
75+
for i := 0; i < n; i++ {
76+
for len(stack) > 0 && primeScores[stack[len(stack)-1]] < primeScores[i] {
77+
topIndex := stack[len(stack)-1]
78+
stack = stack[:len(stack)-1]
79+
nextDominant[topIndex] = i
80+
}
81+
82+
if len(stack) > 0 {
83+
prevDominant[i] = stack[len(stack)-1]
84+
}
85+
86+
stack = append(stack, i)
87+
}
88+
89+
numOfSubarrays := make([]int64, n)
90+
for i := 0; i < n; i++ {
91+
numOfSubarrays[i] = int64(nextDominant[i]-i) * int64(i-prevDominant[i])
92+
}
93+
94+
pq := &PriorityQueue{}
95+
heap.Init(pq)
96+
97+
// Push each number and its index onto the priority queue
98+
for i := 0; i < n; i++ {
99+
heap.Push(pq, Pair2818{value: nums[i], index: i})
100+
}
101+
102+
score := int64(1)
103+
104+
// Process elements while there are operations left
105+
for k > 0 {
106+
// Get the element with the maximum value from the queue
107+
top := heap.Pop(pq).(Pair2818)
108+
num := top.value
109+
index := top.index
110+
111+
// Calculate operations to apply on the current element
112+
operations := int64(k)
113+
if operations > numOfSubarrays[index] {
114+
operations = numOfSubarrays[index]
115+
}
116+
117+
// Update the score
118+
score = (score * power(num, operations)) % mod2818
119+
120+
// Reduce the remaining operations count
121+
k -= int(operations)
122+
}
123+
124+
return int(score)
125+
}
126+
127+
// Helper function to compute the power of a number modulo mod2818
128+
func power(base int, exponent int64) int64 {
129+
res := int64(1)
130+
131+
// Calculate the exponentiation using binary exponentiation
132+
for exponent > 0 {
133+
if exponent%2 == 1 {
134+
res = (res * int64(base)) % mod2818
135+
}
136+
base = (base * base) % mod2818
137+
exponent /= 2
138+
}
139+
140+
return res
141+
}

leetcode/2801-2900/2818.Apply-Operations-to-Maximize-Score/Solution_test.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,30 @@ func TestSolution(t *testing.T) {
1010
// 测试用例
1111
cases := []struct {
1212
name string
13-
inputs bool
14-
expect bool
13+
nums []int
14+
k int
15+
expect int
1516
}{
16-
{"TestCase", true, true},
17-
{"TestCase", true, true},
18-
{"TestCase", false, false},
17+
{"TestCase1", []int{8, 3, 9, 3, 8}, 2, 81},
18+
{"TestCase2", []int{19, 12, 14, 6, 10, 18}, 3, 4788},
1919
}
2020

2121
// 开始测试
2222
for i, c := range cases {
2323
t.Run(c.name+" "+strconv.Itoa(i), func(t *testing.T) {
24-
got := Solution(c.inputs)
24+
got := Solution(c.nums, c.k)
2525
if !reflect.DeepEqual(got, c.expect) {
26-
t.Fatalf("expected: %v, but got: %v, with inputs: %v",
27-
c.expect, got, c.inputs)
26+
t.Fatalf("expected: %v, but got: %v, with inputs: %v %v",
27+
c.expect, got, c.nums, c.k)
2828
}
2929
})
3030
}
3131
}
3232

33-
// 压力测试
33+
// 压力测试
3434
func BenchmarkSolution(b *testing.B) {
3535
}
3636

37-
// 使用案列
37+
// 使用案列
3838
func ExampleSolution() {
3939
}

0 commit comments

Comments
 (0)