1144. 递减元素使数组呈锯齿状
题目描述
给你一个整数数组 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
算法一:贪心 + 分类讨论
思路
- 考虑到题目中分为 奇数索引的数字大 和 偶数索引的数字大 两种情况,我分成两种情况,分别计算它们的操作次数,最后返回最小值。
收获
- 这道题思路很简单,但是我一直没过的点,忽略了 n = 1 / 2 的情况,此时是不需要操作的,否则会出现 数组越界 的情况,直接返回 0 即可。
- 我的代码太复杂了, 可以参考算法二。
算法情况
- 时间复杂度:O(n), n 为 nums 的长度;
- 空间复杂度:O(1)。
代码
class Solution {
public:
int movesToMakeZigzag(vector<int>& nums) {
if(nums.size() < 3) return 0;
int ans = 0;
// 奇数序数的数字比较大
for(int i=0; i<nums.size(); i+=2){
if(i==0){
if(nums[i] >= nums[i+1]){
ans += nums[i] - (nums[i+1] - 1);
}
}
else if(i==nums.size() - 1){
if(nums[i] >= nums[i-1]){
ans += nums[i] - (nums[i-1] - 1);
}
}
else{
// 中间数字
if(nums[i] >= nums[i-1] || nums[i] >= nums[i+1]){
ans += nums[i] - (min(nums[i-1], nums[i+1]) - 1);
}
}
}
// 偶数序数的数字比较大
int cnt = 0;
for(int j=1; j<nums.size(); j+=2){
if(j == nums.size() - 1){
if(nums[j] >= nums[j-1]){
cnt += nums[j] - (nums[j-1] - 1);
}
}
else{
// 中间数字
if(nums[j] >= nums[j-1] || nums[j] >= nums[j+1]){
cnt += nums[j] - (min(nums[j-1], nums[j+1]) - 1);
}
}
}
return min(ans, cnt);
}
};
算法二:贪心 【简洁代码版】
思路
-
思路和算法一差不多, 但是该算法把数组越界的情况都看作 INT_MAX ,不需要在另外判断,方便了很多;
-
情况一: 奇数索引的数字大 ,其实就是考虑 nums[0],nums[2] ,… ,(i % 2 == 0)它们需要满足比两侧奇数索引数字都小;
情况二: 偶数索引的数字大 ,其实就是考虑 nums[1],nums[3] ,… ,(i % 2 == 1)它们需要满足比两侧偶数索引数字都小;
因此,可以统一考虑, i % 2 == 0 时,就考虑情况一,结果记录在 ans[0] ,当 i % 2 == 1 时,就考虑情况二,结果记录在 ans[1] 。
收获
- 数组越界的时候,直接看作 INT_MAX;
算法情况
- 时间复杂度:O(n), 其中 n 为 nums 的长度;
- 空间复杂度:O(C),其中 C 为 2;
代码
class Solution {
public:
int movesToMakeZigzag(vector<int>& nums) {
vector<int> ans(2);
for(int i=0; i<nums.size(); ++i){
int left = i ? nums[i-1] : INT_MAX;
int right = i < nums.size() - 1 ? nums[i+1] : INT_MAX;
ans[i % 2] += max(nums[i] - min(left, right) + 1,0);
}
return min(ans[0], ans[1]);
}
};