复写零(双指针)

一.题目

复写零

给你一个长度固定的整数数组 arr ,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。

注意:请不要在超过该数组长度的位置写入元素。请对输入的数组 就地 进行上述修改,不要从函数返回任何东西。

示例 1:

输入:arr = [1,0,2,3,0,4,5,0]
输出:[1,0,0,2,3,0,0,4]
解释:调用函数后,输入的数组将被修改为:[1,0,0,2,3,0,0,4]

示例 2:

输入:arr = [1,2,3]
输出:[1,2,3]
解释:调用函数后,输入的数组将被修改为:[1,2,3]

提示:

  • 1 <= arr.length <= 104

  • 0 <= arr[i] <= 9

二.题目解析

此题第一眼看上去比较简单,但是做着做着就发现并不是表面上那么"温柔"。

因为题目要求对数组进行'原地'修改,这就导致我们不能另外开一个数组实现模拟。

这就要求我们有很强的模拟+抽象能力。

思路如下:

  1. 我们在草稿纸上对数组进行‘异地’模拟:开一个新数组arr,用1指针遍历原数组,2指针在arr里复写原数组的数据,复写规则是:非零就直接复写,零就写复写两遍。
  2. 转‘异地’为‘就地’:在原数组模拟刚才的异地操作,但模拟到一半我们就会发现后面的元素全都会变成0,所以从前向后复写是不能完成任务的,此时我们不妨换一种思路,从后往前复写。
  3. 但是从后往前复写从倒数第几个数开始复写呢?这就需要我们先找到最后一个复写的数。先‘异地’操作找到最后一个数,再在原数组上从后向前复写,大体思路有了,我们来写代码。
class Solution {
public:
    void duplicateZeros(vector& arr) 
    {
        //cur:遍历数组,dest:复写操作
        int cur = 0,dest = -1,len = arr.size();
        //找到最后一个复写的数
        while(dest= len-1)
            break;
            cur++;
        }
        
        //从后向前完成复写
        while(cur>=0)
        {
            if(arr[cur])
            arr[dest--] = arr[cur--];
            else
            {
                arr[dest--] = 0;
                arr[dest--] = 0;
                cur--;
            }
        }
    }
};

最恶心人的一点来了,提交只过了一部分,为什么呢?原因是没有处理边界情况。当数组倒数第二个数字是0时,我们要复写两次,那么指针就会越界。所以,我们要针对边界情况进行处理。

//处理越界情况
if(dest>=len)
{
    cur--;
    dest-=2;
    arr[len-1] = 0;
}

此时这道题才算是真正解决。下面是具体示例的笔记总结,有需要的可以自取~

复写零(双指针)_第1张图片

复写零(双指针)_第2张图片

你可能感兴趣的:(算法&算法题,算法,数据结构)