算法系列--去除排序数组中的重复元素
来源:互联网 发布:git ssh 非22端口 编辑:程序博客网 时间:2024/06/11 04:12
继续算法系列。今天来说说数组去重的问题。照例,先从最简单的问题说起。
问题描述
给定一个排好序的数组,去除数组中重复的元素使之仅出现一次,返回新的数组长度。要求不需要额外的空间开销。例如,给定数组 A={1,1,2},你写的函数应该返回2,去重之后A={1,2}。
思路分析
排好序的数组中的重复元素一定具备连续排列的特征,这点毋庸置疑。但是根据问题描述,至少有三个问题需要思考:
第一,如何判断相邻的数组元素之间是否相等。很显然,我们至少需要两个游标pointer,i来完成判断。i用来遍历数组当中的元素,而pointer游标应该从第二个位置开始,负责标记A[i]的之后的一个元素,比较A[i]和A[pointer]是否相等,如果不相等,pointer应自增,i自增,如果不等,pointer应保持不变,i自增,继续比较下一个位置。
第二,如何不使用额外的空间来达到去重目的。不使用额外的空间,意味着我们只能使用原来的数组,通过赋值的方式来改变数组中的原有值。根据第一步的分析,我们可以在A[i],A[pointer]不相等的情况下,将A[i]的值赋给A[pointer-1],其实相当于重复元素被挤消失了(这句描述看起来有点诡异,同学们自己在纸上画画就可以知道是啥意思了)。
第三,如何返回去重后的数组长度。在上述分析的基础上,我们可以发现,pointer游标指示的元素都将会是不重复的元素,在循环结束之时,pointer游标应该处于最末一个不重复元素的位置之后。所以pointer就应该是我们想要的结果。
实现代码
思路分析有了,于是我们可以很快写出代码
public class Main {public static void main(String[] args) {int[] array = { 1, 1, 2 };int result = uniqueArray(array);System.out.println(result);}/* * 去除排序数组中的重复元素 */public static int uniqueArray1(int[] array) { if (array.length <= 1) return array.length; int pointer = 1; for (int i = 0; i < array.length; i++) { if (array[i] != array[pointer - 1]) { array[pointer++] = array[i]; } } return pointer; }}输出结果:2,符合预期。
以上算法时间复杂度O(n),空间复杂度O(1),符合要求。
问题变形
如果给定次数要求,允许排序数组中的元素出现两次呢,或者既定的n次呢?算法应该如何写?
先考虑允许排序数组中元素出现两次的情况,例如,给定数组A={1,1,1,2,2,3},你写的函数应该返回长度5,去重后A应该是{1,1,2,2,3}.
思路分析
从对上面简单去重问题的分析,可以知道,必定需要一个游标i来遍历数组元素,而游标pointer此时指向的不应该是A[i]的后一个元素,而应该是A[i]之后的第二个元素A[i+2],其余步骤其实和简单去重问题保持一致。扩展开来,假如说指定排序数组中重复元素最多出现count次,我们这个时候应该很容易推而广之,pointer此时应该指向A[i+count],其余步骤也是完全一致的。
由此,我们便将排序数组中的元素去重问题推向一般化。泛化的排序数组去重问题,可以这样描述
给定排序数组A,要求不使用额外的辅助空间,使A中的元素最多出现count(1,2,3,......)次,写出你的算法。
根据以上描述,我们可以写出以下代码:
/* * 去除排序数组中的重复元素,只允许最多出现两次 */public static int uniqueArray2(int[] array) {if (array.length <= 2)return array.length;int pointer = 2;for (int i = 0; i < array.length; i++) {if (array[i] != array[pointer - 2]) {array[pointer++] = array[i];}}return pointer;}/* * 去除排序中重复元素,允许出现指定次数count次 */public static int uniqueArray3(int[] array, int count) {if (array.length <= count)return array.length;int pointer = count;for (int i = 0; i < array.length; i++) {if (array[i] != array[pointer - count]) {array[pointer++] = array[i];}}return pointer;}
上述算法时间复杂度都是O(n),空间复杂度都是O(1),暂时也没有更高效的算法,测试结果不再给出,同学们可以自行测试。
特别说明:作者也是小学生哈,如果错误和疏漏之处,欢迎大家拍砖和批评指正。
- 算法系列--去除排序数组中的重复元素
- 去除已排序数组中的重复元素
- 去除数组中的重复元素
- 去除数组中的重复元素
- 去除数组中的重复元素
- 去除数组中的重复元素
- 去除数组的重复元素并排序
- 去除js数组中的重复元素
- java去除数组中的重复元素
- 去除列表/数组中的重复元素[转]
- 小白也刷题---leetcode去除数组中的重复元素
- 去除数组中的重复元素---hashset
- 去除有序数组中的重复元素
- 去除js数组中的重复元素
- [算法]删除已排序数组中的重复元素
- 去除数组重复元素
- 算法5—字符串压缩和去除排序好数组里面重复的元素
- 数组去重 (去除数组中的重复元素)
- log日志记录是什么
- HashMap实现原理分析
- 关于MySql在调试过程中出现Driver not loaded Driver not loaded的问题的解决办法
- 九点领导力,用好非常受益
- thinkphp 异步=登陆+注册+注销 jquery+ajax+thinkphp
- 算法系列--去除排序数组中的重复元素
- 领导是什么?
- Archlinux开启ssh服务以使用终端登录
- ubuntu如何添加新的PPA
- win7命令行自由缩放
- [LeetCode-13] Roman to Integer(罗马数字转成阿拉伯数字)
- Java中关于String类和Integer类的用法小结
- 分布式开发以及GitHub使用
- 人善人欺天不欺