1144. 递减元素使数组呈锯齿状

1144. 递减元素使数组呈锯齿状

难度中等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);
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值