一.算法题干
给你一个整数数组nums
,每次操作会从中选择一个元素并将该元素的值减少1。
如果符合下列情况之一,则数组A就是锯齿数组:
每个偶数索引对应的元素都大于相邻的元素,即A[0] > A[1] < A[2] > A[3] < A[4] > …
或者,每个奇数索引对应的元素都大于相邻的元素,即 A[0] < A[1] > A[2] < A[3] > A[4] < …
返回将数组nums
转换为锯齿数组所需的最小操作次数。
二.解题思路
这道题的解题思路相对来说比较简单。首先根据题目中所定义的“锯齿数组”分的两种情况,我也相应地分两种情况进行讨论。首先假定构造出偶数索引大于相邻元素的数组,则遍历所有偶数索引的值,将该值与相邻值进行比较,让相邻值减去一个数,使之恰好小于该偶数索引对应的值,将这个减去的数累加到最后结果上。奇数索引同理。这里需要注意的是两个边界条件要进行单独判断处理。对两种情况分别求完结果后,返回较小值即为所求。
三.实现代码
int movesToMakeZigzag(vector<int>& nums) {
vector<int> ns=nums;
int minv=0,l=ns.size(),minv1=0;
if(l==1) return 0;
for(int i=0;i<l;i+=2)
{
if(i==0)
{
if(ns[i]<=ns[i+1])
{
minv+=ns[i+1]-ns[i]+1;
ns[i+1]=ns[i]-1;
}
}
else if(i==l-1)
{
if(ns[i]<=ns[i-1])
{
minv+=ns[i-1]-ns[i]+1;
ns[i-1]=ns[i]-1;
}
}
else
{
if(ns[i]<=ns[i+1])
{
minv+=ns[i+1]-ns[i]+1;
ns[i+1]=ns[i]-1;
}
if(ns[i]<=ns[i-1])
{
minv+=ns[i-1]-ns[i]+1;
ns[i-1]=ns[i]-1;
}
}
}
ns=nums;
for(int i=1;i<l;i+=2)
{
if(i==l-1)
{
if(ns[i]<=ns[i-1])
{
minv1+=ns[i-1]-ns[i]+1;
ns[i-1]=ns[i]-1;
}
}
else
{
if(ns[i]<=ns[i+1])
{
minv1+=ns[i+1]-ns[i]+1;
ns[i+1]=ns[i]-1;
}
if(ns[i]<=ns[i-1])
{
minv1+=ns[i-1]-ns[i]+1;
ns[i-1]=ns[i]-1;
}
}
}
return min(minv,minv1);
}
四.对比分析
public int movesToMakeZigzag(int[] a) {
int n = a.length;
int c = 0;
for(int i = 1;i < n;i+=2){
int to = a[i-1]-1;
if(i+1 < n)to = Math.min(to, a[i+1] - 1);
if(a[i] < to)continue;
c += a[i] - to;
}
int d = 0;
for(int i = 0;i < n;i+=2){
int to = 999999999;
if(i-1 >= 0)to = Math.min(to, a[i-1]-1);
if(i+1 < n)to = Math.min(to, a[i+1] - 1);
if(a[i] < to)continue;
d += a[i] - to;
}
return Math.min(c, d);
}
这段代码是使用Java实现该算法的,其思路和我的思路主要不同点在于,它是先找出左右两个相邻值中的最小值,然后根据最小值来计算差值。其优点在于代码显然比我的要简洁不少。