有序去重的问题

因为项目需要,需要对一个list集合进行去重,同时要保证不打乱list的顺序


考虑到数据结构的问题。不能直接使用HashSet,毕竟hashset是无需的。老大的意见是使用treeSet,N年不用treeSet这个集合类型,还懵逼了半天。做做整理,记忆强化



Set接口
Set不允许包含相同的元素,如果试图把两个相同元素加入同一个集合中,add方法返回false。
Set判断两个对象相同不是使用==运算符,而是根据equals方法。也就是说,只要两个对象用equals方法比较返回true,Set就不会接受这两个对象。

HashSet
HashSet有以下特点
   不能保证元素的排列顺序,顺序有可能发生变化(性质是无序、无序!!!)
   集合元素可以是null,但只能放入一个null
当向HashSet结合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据 hashCode值来决定该对象在HashSet中存储位置。
简单的说,HashSet集合判断两个元素相等的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode()方法返回值相 等
注意,如果要把一个对象放入HashSet中,重写该对象对应类的equals方法,也应该重写其hashCode()方法。其规则是如果两个对 象通过equals方法比较返回true时,其hashCode也应该相同。另外,对象中用作equals比较标准的属性,都应该用来计算 hashCode的值。

LinkedHashSet
LinkedHashSet集合同样是根据元素的hashCode值来决定元素的存储位置,但是它同时使用链表维护元素的次序。这样使得元素看起 来像是以插入顺序保存的,也就是说,当遍历该集合时候,LinkedHashSet将会以元素的添加顺序访问集合的元素。
LinkedHashSet在迭代访问Set中的全部元素时,性能比HashSet好,但是插入时性能稍微逊色于HashSet(!!!!!)。

TreeSet类
TreeSet是SortedSet接口的唯一实现类,TreeSet可以确保集合元素处于排序状态。TreeSet支持两种排序方式,自然排序 和定制排序,其中自然排序为默认的排序方式。向TreeSet中加入的应该是同一个类的对象。
TreeSet判断两个对象不相等的方式是两个对象通过equals方法返回false,或者通过CompareTo方法比较没有返回0(使用treeSet则集合对象需要实现Comparator接口)
自然排序
自然排序使用要排序元素的CompareTo(Object obj)方法来比较元素之间大小关系,然后将元素按照升序排列。
Java提供了一个Comparable接口,该接口里定义了一个compareTo(Object obj)方法,该方法返回一个整数值,实现了该接口的对象就可以比较大小。
obj1.compareTo(obj2)方法如果返回0,则说明被比较的两个对象相等,如果返回一个正数,则表明obj1大于obj2,如果是 负数,则表明obj1小于obj2。
如果我们将两个对象的equals方法总是返回true,则这两个对象的compareTo方法返回应该返回0
定制排序
自然排序是根据集合元素的大小,以升序排列,如果要定制排序,应该使用Comparator接口,实现 int compare(To1,To2)方法



### 有序数组算法实现 在处理有序数组时,通常可以采用双指针法来优化时间复杂度。以下是基于双指针法的实现方法和代码示例。 #### 算法思路 1. 使用两个指针 `i` 和 `j`,其中 `i` 指向新数组的最后一个非复元素的位置,`j` 用于遍历整个数组。 2. 初始时,`i` 设为 0,表示第一个元素默认是非复的。 3. 遍历数组中的每个元素,如果当前元素与 `i` 所指向的元素不同,则将该元素移动到 `i+1` 的位置,并递增 `i`。 4. 最终返回 `i+1`,即为后数组的新长度。 这种方法的时间复杂度为 O(n),空间复杂度为 O(1),因为是在原数组上进行修改[^1]。 #### 实现代码 以下是使用 Python 实现的代码示例: ```python def remove_duplicates(nums): if not nums: # 处理空数组的情况 return 0 i = 0 # 初始化指针 i for j in range(1, len(nums)): # 遍历数组 if nums[j] != nums[i]: # 如果发现不同的元素 i += 1 # 移动指针 i nums[i] = nums[j] # 将不同的元素放到 i 的位置 return i + 1 # 返回后数组的新长度 ``` #### 示例运行 假设输入数组为 `[1, 1, 2, 2, 3, 4, 4, 5]`,运行上述代码后,输出结果如下: ```python nums = [1, 1, 2, 2, 3, 4, 4, 5] new_length = remove_duplicates(nums) print(nums[:new_length]) # 输出后的数组部分 # 结果为 [1, 2, 3, 4, 5] ``` 此外,也可以使用 Java 实现类似逻辑,参考以下代码: ```java public int removeDuplicates(int[] nums) { if (nums.length == 0) { // 处理空数组的情况 return 0; } int i = 0; // 初始化指针 i for (int j = 1; j < nums.length; j++) { // 遍历数组 if (nums[j] != nums[i]) { // 如果发现不同的元素 i++; // 移动指针 i nums[i] = nums[j]; // 将不同的元素放到 i 的位置 } } return i + 1; // 返回后数组的新长度 } ``` #### 注意事项 - 在实现过程中需要考虑数组为空的情况,以避免空指针异常[^2]。 - 如果需要返回一个新的数组而非修改原数组,可以通过创建一个额外的数组来存储非复元素,但这样会增加空间复杂度为 O(n)[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值