移除数组第一个元素_LeetCode #80 删除排序数组中的重复项II

欢迎来到算法小课堂,今天分享的内容是LeetCode中80.删除排序数组中的重复项II这个题目。 题目描述: 给定一个增序排列数组 nums ,你需要在 原地 删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度。 不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。 示例: 输入:nums = [1,1,1,2,2,3] 输出:5, nums = [1,1,2,2,3] 解释:函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3 。你不需要考虑数组中超出新长度后面的元素。 01 思路讲解 题目要求排序数组中的重复元素最多出现两次。 因此,我们要知道一个元素的出现次数,那怎么知道一个元素的出现次数呢? 可以通过找到下一个和当前考察元素值不同的元素位置,然后用其索引值减去当前考察元素的索引值,结果就是当前元素在数组中的出现次数。 如下图,变量i所指向的元素为当前考察的元素,其索引值为0。变量k所指向的元素为下一个和当前考察元素值不同的元素,其索引值为3。两者之差为3,即当前考察的元素1在数组中共出现3次。 a60fbb1355e9ae5b6678925cd608e7de.png 在知道当前考察元素的出现次数后,接着要做的就是看其出现次数是否大于两次。 如果当前考察的元素出现次数小于等于2,则其在结果数组中出现次数不变;如果当前考察的元素出现次数大于2,则其在结果数组中出现次数为2次。 在确定当前考察元素,在结果数组中应该出现的次数,并将其存入结果数组中之后,接下来要做的就是继续考察下一个元素,即和当前考察元素值不等的元素。 以上是对整体思路的梳理,接下来以数组{1, 1, 1, 2, 2, 3}为例来看下具体过程。 首先,定义变量j,其初始值为0,区间[0,j)表示移除重复元素后,结果数组中的元素。变量i的初始值也为0,指向当前考察的元素。 dca7f5e1f89652af32011f0c5d54cf22.png 接着,查找第一个和当前所考察元素值不相等的元素,用变量k表示。在数组{1, 1, 1, 2, 2, 3}中和当前考察元素1不相等的第一个元素是2。 a60fbb1355e9ae5b6678925cd608e7de.png 根据上面整体思路讲解的,当前考察的元素1出现次数为3次,即变量k的值减去变量i的值。 接着要做的就是将变量i所指向的元素1复制两个到结果数组中,因为重复元素最多出现2次。每次在将变量i指向的元素复制到结果数组中后,变量j向后移动一个位置。 8d67411ad6be2a1439abaf3da13a65e7.gif 接着考察下一个元素。将变量k的值赋予变量i,即变量i移到变量k所在的位置。 3a3f737f3b396bc51f967d599cda2c0a.gif 此时变量i所指向的元素2为当前考察的元素,重复上述过程,即可将排序数组中重复的元素移除,使其最多出现两次。 f3108984558c54fc77f4853a1363a33e.png 动画演示 上述思路的代码实现如下:
public int removeDuplicates(int[] nums) {    int[] resNums = new int[nums.length];    // 定义变量j,其初始值为0,    // 区间[0,j)表示移除重复元素后,结果数组中的元素    int j = 0;    // 当前考察的元素    int i = 0;    while (i < nums.length) {        // 查找下一个和当前元素值不相等的元素的下标        int k = nextDifferentNum(i, nums);        // k-j的值表示当前考察的元素出现的次数        // 而题目要求每个元素最多出现2次        // 因此,需要将k-j的值和2比较,取两者最小值        // 即curNumCount值最大为2        int curNumCount = Math.min(2, k - i);        // 将当前考察的元素最多只保存2个        for(int n = 0; n < curNumCount; n++) {            // i+n表示当前考察元素应放在数组的哪个位置            resNums[j] = nums[i];            j++;        }        // 更新i的值为下一个和其值不相等的元素的索引值        // 即下一个要考察的元素        i = k;    }    // 将结果数组中的元素复制到原数组    for(int r = 0; r < j; r++) {        nums[r] = resNums[r];    }    return j;}private int nextDifferentNum(int index, int[] nums) {    for(int m = index; m < nums.length; m++) {        if (nums[m] != nums[index]) {            return m;        }    }    return nums.length;}
这里的代码实现,借助了一个新的数组来保存原数组中移除重复项后的结果。但题目要求是原地删除。因此,需将复制元素到结果数组中改为原地复制。 02 代码实现
public int removeDuplicates(int[] nums) {    // 定义变量j,其初始值为0,    // 区间[0,j)表示移除重复元素后,结果数组中的元素    int j = 0;    // 当前考察的元素    int i = 0;    while (i < nums.length) {        // 查找下一个和当前元素值不相等的元素的下标        int k = nextDifferentNum(i, nums);        // k-j的值表示当前考察的元素出现的次数        // 而题目要求每个元素最多出现2次        // 因此,需要将k-j的值和2比较,取两者最小值        // 即curNumCount值最大为2        int curNumCount = Math.min(2, k - i);        // 将当前考察的元素最多只保存2个        for(int n = 0; n < curNumCount; n++) {            // 原地删除            nums[j] = nums[i];            j++;        }        // 更新i的值为下一个和其值不相等的元素的索引值        // 即下一个要考察的元素        i = k;    }    return j;}private int nextDifferentNum(int index, int[] nums) {    for(int m = index; m < nums.length; m++) {        if (nums[m] != nums[index]) {            return m;        }    }    return nums.length;}
感谢您的阅读。 如有错误, 欢迎在公众号后台留言指出。 下一篇我们将学习新的内容,敬请期待。 PS:如果文章对您有一点点帮助,请动动手指,分享、收藏、点赞、在看都可以,这会让我开心一整天,再次感谢您的阅读。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值