难度中等116收藏分享切换为英文接收动态反馈
给你一个整数数组 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 = [1,2,3] 输出:2 解释:我们可以把 2 递减到 0,或把 3 递减到 1。
示例 2:
输入:nums = [9,6,1,6,2] 输出:4
提示:
1 <= nums.length <= 1000
1 <= nums[i] <= 1000
思路:不管是每个偶数索引对应的元素都大于相邻的元素还是每个奇数索引对应的元素都大于相邻的元素,绕不开的一个问题就是如何让一个位置的数nums[i]比两边小,实际上等价于比两边值中更小的那个还小,而最小操作数意味着我们尽可能少地减少nums[i],那么在最少操作次数下的目标值为min(nums[i-1],nums[i+1]) - 1,操作步数为nums[i] - ( min(nums[i-1],nums[i+1])-1 )。还需要处理的一个事情是nums[i]本身就满足nums[i] < min(nums[i-1],nums[i+1]),此时会得到操作数nums[i] - ( min(nums[i-1],nums[i+1]) -1 ) <= 0,但是其实对于这种情况我们是不需要处理的,因此最终每个位置的操作步数为max(0, nums[i] - ( min(nums[i-1],nums[i+1]) -1))。
现在我们只需要分两种情况(每个偶数索引对应的元素都大于相邻的元素;每个奇数索引对应的元素都大于相邻的元素)分别计算一下操作步数,取小即可啦
class Solution {
public:
int movesToMakeZigzag(vector<int>& nums) {
//BFS
//return min(DFS(nums, true, 0, 0), DFS(nums, false, 0, 0));
//1.计算奇最小情况 直接减小奇位置还是间接变小偶位置
int add_step = 0, odd_step = 0, neighbour_min, idx;
for(idx = 1; idx < nums.size(); idx += 2){//把奇位置变小
neighbour_min = nums[idx - 1];
if(idx + 1 < nums.size()){
neighbour_min = min(neighbour_min, nums[idx + 1]);
}
add_step += max(0, nums[idx] - (neighbour_min - 1));
}
//2.计算偶情况
for(idx = 0; idx < nums.size(); idx += 2){//把偶位置变小
neighbour_min = 0x3f3f3f3f;
if(idx > 0){//算一下左边
neighbour_min = min(neighbour_min, nums[idx - 1]);
}
if(idx + 1 < nums.size()){
neighbour_min = min(neighbour_min, nums[idx + 1]);
}
odd_step += max(0, nums[idx] - (neighbour_min - 1));
}
return min(add_step, odd_step);
}
};