题目:
给你一个整数数组 nums,每次 操作 会从中选择一个元素并 将该元素的值减少 1。
如果符合下列情况之一,则数组 A 就是 锯齿数组:
每个偶数索引对应的元素都大于相邻的元素,即 A[0] > A[1] < A[2] > A[3] < A[4] > ...
或者,每个奇数索引对应的元素都大于相邻的元素,即 A[0] < A[1] > A[2] < A[3] > A[4] < ...
返回将数组 nums 转换为锯齿数组所需的最小操作次数。
标签:数组、贪心
提示:
1 <= nums.length <= 1000
1 <= nums[i] <= 1000
分析:
- 分别利用两个判断条件,计算将数组转化成锯齿数组需要的操作次数;然后返回两个值中较小的那个;
- 考虑边界:索引为0的元素,只需要与索引为1的元素比较;索引为n-1的元素,只需要与索引为n-2的元素比较;
- 在每一次比较中,基准元素不改变,其相邻元素减小;
代码:
class Solution:
def movesToMakeZigzag(self, nums: list[int]) -> int:
n = len(nums)
if n == 1:
return 0
even_num, odd_num = self.check(nums, n)
if even_num >= 0 and odd_num >= 0:
return min(even_num, odd_num)
elif even_num >= 0 and odd_num < 0:
return even_num
elif even_num < 0 and odd_num >= 0:
return odd_num
else:
return -2 # 若两种判定方式均无法完成转换,返回-2表示失败
def check(self, nums: list[int], n: int) -> int: # 若无法完成锯齿数组的转换,则返回-1,表示转换失败
i = 0
ke = 2 * i
ko = 2 * i + 1
optne, optno = 0, 0 # 总的操作次数
even_nums, odd_nums = nums[:], nums[:]
while ke < n and ko <= n:
if optne != -1 and ke < n:
optne = self.classfy_check(even_nums, ke, n, optne)
if optno != -1 and ko < n:
optno = self.classfy_check(odd_nums, ko, n, optno)
i += 1
ke = 2 * i
ko = 2 * i + 1
return optne, optno
def classfy_check(self, numl: list, k: int, n: int, optn: int) -> int:
if k == 0:
if numl[k] <= numl[k + 1]:
opt_res = self.operation(numl[k], numl[k + 1])
optn += opt_res[0]
numl[k + 1] = opt_res[1]
return optn
if k + 1 == n:
if numl[k] <= numl[k - 1]:
opt_res = self.operation(numl[k], numl[k - 1])
optn += opt_res[0]
numl[k - 1] = opt_res[1]
return optn
if numl[k] <= numl[k + 1]:
opt_res = self.operation(numl[k], numl[k + 1])
optn += opt_res[0]
numl[k + 1] = opt_res[1]
if numl[k] <= numl[k - 1]:
opt_res = self.operation(numl[k], numl[k - 1])
optn += opt_res[0]
numl[k - 1] = opt_res[1]
return optn
def operation(self, base: int, ngb: int) -> list[int]: # 返回达到要求的操作次数,同时修改邻居元素的值为操作后的值
opt = 0 # 操作次数
while ngb >= base:
ngb -= 1
opt += 1
return [opt, ngb]
test = Solution()
print(test.movesToMakeZigzag([7,4,8,9,7,7,5]))