【问题描述】:
给你一个整数数组 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
【思路:】
这题的思路需要好好想一下
如果A[i]数字在锯齿化之后呈现这种形式:A[i - 1] < A[i] > A[i + 1], 那么我们将其状态status表示为0
若是这种A[i - 1] > A[i] < A[i + 1],那么我们将A[i]状态status表示为1。
对第i位数字A[i]分析,如果想要其状态为0,那么第i - 1位数字状态一定是1;
在这种情况下,如果在 锯齿化之前 A[i] > A[i - 1],那就意味着我们不需要进行任何操作就满足A[i]状态为1;若 锯齿化之前 A[i] < A[i - 1],那么我们要把A[i-1]减少,直到A[i - 1]<A[i]才能满足锯齿化A[i]状态为1。
分析第i位数字状态为1的话道理是一样的。
所以根据这个思路,写出递归:
class Solution {
public int movesToMakeZigzag(int[] nums) {
int[] temp = new int[nums.length];
for(int i = 0;i < temp.length;i++){
temp[i] = nums[i];
}
int res1 = recursion(nums.length - 1, 1, temp);
for(int i = 0;i < temp.length;i++){
temp[i] = nums[i];
}
int res2 = recursion(nums.length - 1, 0, temp);
res1 = Math.min(res1, res2);
return res1;
}
public int recursion(int n, int status, int [] nums){
//如果搜到0了,返回0
if(n == 0) return 0;
//如果这个数是要比周围的数小
if(status == 1){
//如果前一个数还比你大,那么你肯定就不需要动了
if(nums[n - 1] > nums[n]){
return recursion(n - 1, 0, nums);
}else if(nums[n - 1] < nums[n]){
int cnt = nums[n] - nums[n - 1] + 1;
nums[n] = nums[n - 1] - 1;
return recursion(n - 1, 0, nums) + cnt;
}else{
nums[n] = nums[n] - 1;
return recursion(n - 1, 0, nums) + 1;
}
//如果这个数要比周围的数大
}else{
//如果前一个数比你小,那么你就不需要动了
if(nums[n - 1] < nums[n]){
return recursion(n - 1, 1, nums);
}else if(nums[n - 1] > nums[n]){
int cnt = nums[n - 1] - nums[n] + 1;
nums[n - 1] = nums[n] - 1;
return recursion(n - 1, 1, nums) + cnt;
}else{
nums[n - 1] = nums[n] - 1;
return recursion(n - 1, 1, nums) + 1;
}
}
}
}