-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path3717-MinimumOperationsToMakeTheArrayBeautiful.go
More file actions
192 lines (173 loc) · 6.3 KB
/
3717-MinimumOperationsToMakeTheArrayBeautiful.go
File metadata and controls
192 lines (173 loc) · 6.3 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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
package main
// 3717. Minimum Operations to Make the Array Beautiful
// You are given an integer array nums.
// An array is called beautiful if for every index i > 0, the value at nums[i] is divisible by nums[i - 1].
// In one operation, you may increment any element of nums by 1.
// Return the minimum number of operations required to make the array beautiful.
// Example 1:
// Input: nums = [3,7,9]
// Output: 2
// Explanation:
// Applying the operation twice on nums[1] makes the array beautiful: [3,9,9]
// Example 2:
// Input: nums = [1,1,1]
// Output: 0
// Explanation:
// The given array is already beautiful.
// Example 3:
// Input: nums = [4]
// Output: 0
// Explanation:
// The array has only one element, so it's already beautiful.
// Constraints:
// 1 <= nums.length <= 10^5
// 1 <= nums[i] <= 10^9
import "fmt"
import "slices"
// Wrong Answer 916 / 1047 testcases passed
// 美丽数组的定义:对于数组中的每个元素(除了第一个元素),该元素必须能被前一个元素整除
// 解题思路:
// 1. 从数组的第二个元素开始遍历,计算当前元素与前一个元素的余数
// 2. 如果余数不为 0,计算需要增加的值(使得当前元素能被前一个元素整除),并将该值累加到总操作次数中
// 3. 更新当前元素的值(增加后的值),并将其设为下一次迭代的前一个元素
// 4. 遍历完成后,返回总操作次数
func minOperations(nums []int) int {
res, n, prev := 0, len(nums), nums[0]
if n <= 1 { return 0 } // 如果数组长度小于等于 1,数组已经是美丽数组,直接返回 0
for i := 1; i < n; i++ {
curr:= nums[i]
rem := curr % prev // 计算当前元素与前一个元素的余数
if rem != 0 { // 如果余数不为 0,计算需要增加的值(使得当前元素能被前一个元素整除),并将该值累加到总操作次数中。
add := prev - rem
res += add
curr += add
}
prev = curr // 更新当前元素的值(增加后的值),并将其设为下一次迭代的前一个元素
}
return res
}
// Wrong Answer 916 / 1047 testcases passed
func minOperations1(nums []int) int {
res, n, prev := 0, len(nums), nums[0]
if n <= 1 {
return 0
}
for i := 1; i < n; i++ {
curr := nums[i]
k := (curr + prev - 1) / prev
res += (k * prev - curr)
prev= k * prev
}
return res
}
func minOperations2(nums []int) int {
n, inf := len(nums), 1 << 61
if n == 0 { return 0 }
mx := nums[0]
for _, v := range nums { // 找到数组中的最大值
if v > mx {
mx = v
}
}
threshold := 2 * mx
dp := make([]int, threshold + 1)
for i := range dp { // 初始化 dp 数组,填充无穷大
dp[i] = inf
}
dp[nums[0]] = 0
for i := 1; i < n; i++ { // 动态规划核心逻辑
// 临时数组存储当前轮次的 dp 值(避免覆盖)
newDp := make([]int, threshold + 1)
copy(newDp, dp)
for j := threshold; j >= nums[i]; j-- { // 倒序遍历 j,从 threshold 到 nums[i]
curr := inf
// 遍历 k 从 nums[i-1] 到 j,寻找能整除 j 的 k
for k := nums[i-1]; k <= j; k++ {
if j % k == 0 && dp[k] != inf {
// 计算操作数:之前的操作数 + 当前需要增加的数值
op := dp[k] + (j - nums[i])
if op < curr {
curr = op
}
}
}
newDp[j] = curr
}
for j := 0; j < nums[i]; j++ { // 将小于 nums[i] 的位置重置为无穷大(无法通过增加得到)
newDp[j] = inf
}
dp = newDp
}
res := inf
for _, v := range dp { // 找到 dp 数组中的最小值
if v < res {
res = v
}
}
return res
}
func minOperations3(nums []int) int {
const inf = 1 << 61
top := slices.Max(nums) * 2
f, g := make([]int, top), make([]int, top)
for i := range f {
f[i] = inf
}
f[nums[0]] = 0
for _, v := range nums[1:] {
for i := range g {
g[i] = inf
}
for preVal, preCnt := range f {
if preCnt >= inf {
continue
}
for newVal := (v + preVal - 1) / preVal * preVal; newVal < top; newVal += preVal {
g[newVal] = min(g[newVal], preCnt + newVal - v)
}
}
f, g = g, f
}
return slices.Min(f)
}
func main() {
// Example 1:
// Input: nums = [3,7,9]
// Output: 2
// Explanation:
// Applying the operation twice on nums[1] makes the array beautiful: [3,9,9]
fmt.Println(minOperations([]int{3,7,9})) // 2
// Example 2:
// Input: nums = [1,1,1]
// Output: 0
// Explanation:
// The given array is already beautiful.
fmt.Println(minOperations([]int{1,1,1})) // 0
// Example 3:
// Input: nums = [4]
// Output: 0
// Explanation:
// The array has only one element, so it's already beautiful.
fmt.Println(minOperations([]int{4})) // 0
fmt.Println(minOperations([]int{5,13,18})) // 9
fmt.Println(minOperations([]int{1,2,3,4,5,6,7,8,9})) // 14
fmt.Println(minOperations([]int{9,8,7,6,5,4,3,2,1})) // 36
fmt.Println(minOperations1([]int{3,7,9})) // 2
fmt.Println(minOperations1([]int{1,1,1})) // 0
fmt.Println(minOperations1([]int{4})) // 0
fmt.Println(minOperations1([]int{5,13,18})) // 9
fmt.Println(minOperations1([]int{1,2,3,4,5,6,7,8,9})) // 14
fmt.Println(minOperations1([]int{9,8,7,6,5,4,3,2,1})) // 36
fmt.Println(minOperations2([]int{3,7,9})) // 2
fmt.Println(minOperations2([]int{1,1,1})) // 0
fmt.Println(minOperations2([]int{4})) // 0
fmt.Println(minOperations2([]int{5,13,18})) // 9
fmt.Println(minOperations2([]int{1,2,3,4,5,6,7,8,9})) // 14
fmt.Println(minOperations2([]int{9,8,7,6,5,4,3,2,1})) // 36
fmt.Println(minOperations3([]int{3,7,9})) // 2
fmt.Println(minOperations3([]int{1,1,1})) // 0
fmt.Println(minOperations3([]int{4})) // 0
fmt.Println(minOperations3([]int{5,13,18})) // 9
fmt.Println(minOperations3([]int{1,2,3,4,5,6,7,8,9})) // 14
fmt.Println(minOperations3([]int{9,8,7,6,5,4,3,2,1})) // 36
}