leetcode -- 1089 复写零 【双指针 C/C++】

原题链接:1089. 复写零 - 力扣(LeetCode)

题目解析

要求在保持原数组大小的情况下,将数组中的0复习,也就是改成两倍。然后非零的元素与0的相对位置保持不变,如果复写的数组已经到数组的边界就结束复写,就如示例1那样。

算法原理

使用双指针。

先用双指针异地模拟,再“就地”模拟,达到题目要求。

双指针创建:

cur:遍历数组

dest:指向已复写的最后一个元素

异地模拟

1 0 2 3 0 4 5 0 

复写

1 0 0 2 3 0 0 4

原地模拟

从左往右复写会造成对原本数组的元素的覆盖

所以从右往左 或者说从后往前

cur :指向最后一个待复写的元素

dest : 指向数组的最后一个元素

可见从后往前复写就可以达到要求。

现在问题是如何找到最后一个需要复写的元素,也就是cur的起始位置该怎么找。

寻找最后一个“复写”元素位置

只要按照下面步骤,就能找到最后一个需要“复写”的位置。

结束时,cur指向的元素就是最后一个需要“复写”的位置

1.判断cur位置的值

2.决定dest往前走一步还是两步

3.判断dest是否到结束位置

4.cur++

处理边界情况

当最后一个复写元素是0时,dest连续走两步会直接到n(假设n为数组元素个数)位置,发生数组越界。

这时将数组的最后一个元素赋为0,然后cur向前移动一步,dest向前移动两步。

eg:

原      1  0  2  3  0  4    

复写  1  0  0  2  3  0 (0)

这种情况下,最后一个0理论上dest是要进行复写的,但是已经发生了数组越界,leetcode上会直接报错。所以我们针对这种情况,先将这个0元素处理掉,然后让cur指向上一个需要处理的复写元素。

也就是说,这个情况下的cur指向的是 3 (原本应该是0)然后dest指向的是0

这是在找完最后一个复写元素时,两个指针的指向情况

这是在处理完边界后的双指针指向情况

关注不迷路~更多算法解析持续更新中~!

代码编写

c语言代码

void duplicateZeros(int* arr, int arrSize) {
    //1.找到最后一个需要“复写”的数
    int dest = -1;
    int cur = 0;
    while(cur < arrSize)
    {
        if(arr[cur] == 0)
        {
            dest+=2;
        }
        else
        {
            dest++;
        }
        if(dest >= arrSize-1)
            break;
        cur++;
    }
    //2.处理dest越界情况
    if(dest == arrSize)
    {
        cur--;
        arr[arrSize-1] = 0;
        dest-=2;
    }
    //3.从后往前复写
    while(cur>=0)
    {
        if(arr[cur] == 0)
        {
            arr[dest--] =0;
            arr[dest--] = 0;
            cur--;
        }
        else
        {
            arr[dest--] = arr[cur--];
        }
    }
}

C++代码

class Solution {
public:
    void duplicateZeros(vector<int>& arr) {
 //1.找到最后一个需要“复写”的数
    int dest = -1, cur = 0,n = arr.size();
    while(cur < n)
    {
        if(arr[cur] )
        {
            dest++;
        }
        else
        {
            dest+=2;
        }
        if(dest >= n -1) break;
        cur++;
    }
    //2.处理dest越界情况
    if(dest ==n)
    {
        arr[n-1] = 0;
        cur--; 
        dest-=2;
    }
    //3.从后往前复写
    while(cur>=0)
    {
        if(arr[cur])
        {
            arr[dest--] = arr[cur--];
        }
        else
        {
            arr[dest--] =0;
            arr[dest--] = 0;
            cur--;
        }
    }
    }
};

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值