-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path2835-MinimumOperationsToFormSubsequenceWithTargetSum.go
More file actions
160 lines (144 loc) · 5.99 KB
/
2835-MinimumOperationsToFormSubsequenceWithTargetSum.go
File metadata and controls
160 lines (144 loc) · 5.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package main
// 2835. Minimum Operations to Form Subsequence With Target Sum
// You are given a 0-indexed array nums consisting of non-negative powers of 2, and an integer target.
// In one operation, you must apply the following changes to the array:
// 1. Choose any element of the array nums[i] such that nums[i] > 1.
// 2. Remove nums[i] from the array.
// 3. Add two occurrences of nums[i] / 2 to the end of nums.
// Return the minimum number of operations you need to perform so that nums contains a subsequence whose elements sum to target.
// If it is impossible to obtain such a subsequence, return -1.
// A subsequence is an array that can be derived from another array by deleting some
// or no elements without changing the order of the remaining elements.
// Example 1:
// Input: nums = [1,2,8], target = 7
// Output: 1
// Explanation: In the first operation, we choose element nums[2]. The array becomes equal to nums = [1,2,4,4].
// At this stage, nums contains the subsequence [1,2,4] which sums up to 7.
// It can be shown that there is no shorter sequence of operations that results in a subsequnce that sums up to 7.
// Example 2:
// Input: nums = [1,32,1,2], target = 12
// Output: 2
// Explanation: In the first operation, we choose element nums[1]. The array becomes equal to nums = [1,1,2,16,16].
// In the second operation, we choose element nums[3]. The array becomes equal to nums = [1,1,2,16,8,8]
// At this stage, nums contains the subsequence [1,1,2,8] which sums up to 12.
// It can be shown that there is no shorter sequence of operations that results in a subsequence that sums up to 12.
// Example 3:
// Input: nums = [1,32,1], target = 35
// Output: -1
// Explanation: It can be shown that no sequence of operations results in a subsequence that sums up to 35.
// Constraints:
// 1 <= nums.length <= 1000
// 1 <= nums[i] <= 2^30
// nums consists only of non-negative powers of two.
// 1 <= target < 2^31
import "fmt"
import "sort"
import "container/heap"
type PriorityQueue []int
func (pq PriorityQueue) Len() int { return len(pq) }
func (pq PriorityQueue) Less(i, j int) bool { return pq[i] > pq[j] }
func (pq PriorityQueue) Swap(i, j int) { pq[i], pq[j] = pq[j], pq[i] }
func (pq *PriorityQueue) Push(x interface{}) { *pq = append(*pq, x.(int)) }
func (pq *PriorityQueue) Pop() interface{} {
old := *pq
n := len(old)
x := old[n - 1]
*pq = old[0 : n - 1]
return x
}
func minOperations(nums []int, target int) int {
pq := make(PriorityQueue, len(nums))
copy(pq, nums)
heap.Init(&pq)
sum, count := 0, 0
for _, v := range nums {
sum += v
}
if sum < target { return -1 }
for len(pq) > 0 {
v := heap.Pop(&pq).(int)
sum -= v
if v <= target {
target -= v
} else if v > target && sum < target {
count++
heap.Push(&pq, v / 2)
heap.Push(&pq, v / 2)
sum += v
}
}
return count
}
func minOperations1(nums []int, target int) int {
sort.Ints(nums)
res, sum, record := 0, 0, [31]int{}
for i := 0; i < len(nums); i++ {
v, count := nums[i], -1
for v > 0 {
v /= 2
count++
}
record[count]++
}
for i := 0; 1 << i <= target; i++ {
if (1 << i) & target != 0 {
if record[i] > 0 { // 该位需要1
record[i]--
sum += (record[i] * (1 << i)) // 把多的转成 1
} else if sum >= (1 << i) {
sum -= (1 << i)
} else {
hit := false
for j := i + 1; j < len(record); j++ {
if record[j] > 0 {
record[j]--
// 把 j / 2 , 如果需要 8 32 -> 16 -> 8
// i = 3 j = 5
res += j - i
j--
// 增加后面计数
for ; j > i; j-- {
record[j]++
}
hit = true
break
}
}
if !hit { return -1 }
// 如果不行通过分解比自己大的数据得到
}
} else {
sum += record[i] * (1 << i)
}
}
return res
}
func main() {
// Example 1:
// Input: nums = [1,2,8], target = 7
// Output: 1
// Explanation: In the first operation, we choose element nums[2]. The array becomes equal to nums = [1,2,4,4].
// At this stage, nums contains the subsequence [1,2,4] which sums up to 7.
// It can be shown that there is no shorter sequence of operations that results in a subsequnce that sums up to 7.
fmt.Println(minOperations([]int{1,2,8}, 7)) // 1
// Example 2:
// Input: nums = [1,32,1,2], target = 12
// Output: 2
// Explanation: In the first operation, we choose element nums[1]. The array becomes equal to nums = [1,1,2,16,16].
// In the second operation, we choose element nums[3]. The array becomes equal to nums = [1,1,2,16,8,8]
// At this stage, nums contains the subsequence [1,1,2,8] which sums up to 12.
// It can be shown that there is no shorter sequence of operations that results in a subsequence that sums up to 12.
fmt.Println(minOperations([]int{1,32,1,2}, 12)) // 2
// Example 3:
// Input: nums = [1,32,1], target = 35
// Output: -1
// Explanation: It can be shown that no sequence of operations results in a subsequence that sums up to 35.
fmt.Println(minOperations([]int{1,32,1}, 35)) // -1
fmt.Println(minOperations([]int{1,2,3,4,5,6,7,8,9}, 2)) // 0
fmt.Println(minOperations([]int{9,8,7,6,5,4,3,2,1}, 2)) // 0
fmt.Println(minOperations1([]int{1,2,8}, 7)) // 1
fmt.Println(minOperations1([]int{1,32,1,2}, 12)) // 2
fmt.Println(minOperations1([]int{1,32,1}, 35)) // -1
fmt.Println(minOperations1([]int{1,2,3,4,5,6,7,8,9}, 2)) // 0
fmt.Println(minOperations1([]int{9,8,7,6,5,4,3,2,1}, 2)) // 0
}