双指针算法实例2(复写零)

题目:

给你一个长度固定的整数数组 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 找到最后一个要被写入的数据:

   cur=0(遍历数组),dest=-1 (占位),初始化为-1表示还未占位

   a 如果cur指向的数据是非0元素,dest++,占1个位置

   b 如果cur指向的数据是0,dest+=2,占两个位置

   c 每一次都要判断dest是否>=n-1,dest==n-1表示占位已经满了,dest==n是因为当最后一个写入的数据是0,要复写两次,且dest此时指向是n-1的位置,dest再占一个位置,那就越界了

     一旦占位已满或者dest越界,就结束循环,此时cur指向的是要被写入的最后一个数据

2 处理边界情况:dest==n,被写入的最后一个元素是0且位置不够,发生越界,只能写入一次

   让arr[n-1]=0,处理完成后,cur--,指向下一个要写入的数据(该写入几次就写入几次)

                                               dest-=2,指向下一个要写入数据的位置

 3 正常写入数据

    非0写入一次,0写入两次

代码实现:

class Solution 
{
public:
    void duplicateZeros(vector& arr)
    {
        int cur = 0;//遍历数组,找到最后一个要被写入的数字
        int dest = -1;//为被写入的数字模拟占位
        int n = arr.size();
        while(cur=n-1)//位置已经满了,已经找到最后一个要被写入的数字
            {
                break;
            }
            cur++;
        }

        if(dest==n)//当最后一个要被写入的数据是0时,0要复写两次,但是dest已经越界了
        {
            arr[n-1] = 0;//越界的位置不用写0了,在没有越界的位置写入一个0
            cur--;//指向下一个要写入的数据
            dest-=2;//指向下一个要写入数据的位置
        }

        while(cur>=0)//写入数据
        {
            if(arr[cur])//非0,写入1次
            {
                arr[dest--] = arr[cur--];
            }
            else//0,写入两次
            {
                arr[dest--] = 0;
                arr[dest--] = 0;
                cur--;
            }
        }
    }
};

你可能感兴趣的:(方法集合,算法)