Given an array nums
of integers, a move consists of choosing any element and decreasing it by 1.
An array A
is a zigzag array if either:
- Every even-indexed element is greater than adjacent elements, ie.
A[0] > A[1] < A[2] > A[3] < A[4] > ...
- OR, every odd-indexed element is greater than adjacent elements, ie.
A[0] < A[1] > A[2] < A[3] > A[4] < ...
Return the minimum number of moves to transform the given array nums
into a zigzag array.
Example 1:
Input: nums = [1,2,3]
Output: 2
Explanation: We can decrease 2 to 0 or 3 to 1.
Example 2:
Input: nums = [9,6,1,6,2]
Output: 4
Constraints:
1 <= nums.length <= 1000
1 <= nums[i] <= 1000
这道题说是每次可以给数组中的任意数字减小1,现在想将数组变为之字形,就是数字大和小交替出现,有两种,一种是偶数坐标的数字均大于其相邻两个位置的数字,一种是奇数坐标的数字均大于其相邻的两个位置的数字。对于第一种情况来说,其奇数坐标位置的数字就均小于其相邻两个位置的数字,同理,对于第二种情况,其偶数坐标位置的数字就均小于其相邻两个位置的数字。这里我们可以分两种情况来统计减少次数,一种是减小所有奇数坐标上的数字,另一种是减小所有偶数坐标上的数字。减小的方法是找到相邻的两个数字中的较小那个,然后比其小1即可,即可用 nums[i] - min(left, right) + 1
来得到,若得到了个负数,说明当前数字已经比左右的数字小了,不需要再减小了,所以需要跟0比较,取较大值。这里用了一个大小为2的 res 数组,这用直接根据当前坐标i,通过 i%2
就可以更新对应的次数了,最终取二者中的较小值返回即可,参见代码如下:
class Solution {
public:
int movesToMakeZigzag(vector<int>& nums) {
int n = nums.size(), res[2] = {0, 0};
for (int i = 0; i < n; ++i) {
int left = i > 0 ? nums[i - 1] : 1001;
int right = i < n - 1 ? nums[i + 1] : 1001;
res[i % 2] += max(0, nums[i] - min(left, right) + 1);
}
return min(res[0], res[1]);
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/1144
类似题目:
Binary Tree Zigzag Level Order Traversal
参考资料:
https://leetcode.com/problems/decrease-elements-to-make-array-zigzag/
LeetCode All in One 题目讲解汇总(持续更新中…)
转载请注明来源于 Grandyang 的博客 (grandyang.com),欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 grandyang@qq.com