双指针-在原来的数组上修改元素(应用于)
左指针不动,右指针移动,当移动到与左指针不同的元素时,左指针移动一位,将那位的元素改为右指针的值;随后,右指针继续移动。
public static int removeDuplicates(int[] nums){
//双指针
int num = 0;
for (int i = 1; i < nums.length; i++) {
if (nums[num] != nums[i]){
num++;
nums[num] = nums[i];
}
}
return num + 1;
}
-
利用++left,更简洁
//双指针解决
public int removeDuplicates(int[] A) {
//边界条件判断
if (A == null || A.length == 0)
return 0;
int left = 0;
for (int right = 1; right < A.length; right++)
//如果左指针和右指针指向的值一样,说明有重复的,
//这个时候,左指针不动,右指针继续往右移。如果他俩
//指向的值不一样就把右指针指向的值往前挪
if (A[left] != A[right])
A[++left] = A[right];
return ++left;
}
// 作者:数据结构和算法
// 链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/x2gy9m/?discussion=4Zkrel
// 来源:力扣(LeetCode)
// 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
-
另外一种解法
public int removeDuplicates(int[] A) {
int count = 0;//重复的数字个数
for (int right = 1; right < A.length; right++) {
if (A[right] == A[right - 1]) {
//如果有重复的,count要加1
count++;
} else {
//如果没有重复,后面的就往前挪
A[right - count] = A[right];
}
}
//数组的长度减去重复的个数
return A.length - count;
}
// 作者:数据结构和算法
// 链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/x2gy9m/?discussion=4Zkrel
// 来源:力扣(LeetCode)
// 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
扩展
-
保留插入顺序的集合:LinkedHashSet类
要创建一个保留元素插入顺序的集合,你可以使用 LinkedHashSet
类。LinkedHashSet
是 HashSet
的子类,但它维护了一个运行于所有条目的双重链接列表,这使得迭代顺序与插入顺序相同。下面是使用 LinkedHashSet
创建并操作一个集合的示例:
import java.util.LinkedHashSet;
import java.util.Set;
public class OrderedSetExample {
public static void main(String[] args) {
// 创建一个 LinkedHashSet
Set<String> orderedSet = new LinkedHashSet<>();
// 添加一些元素
orderedSet.add("Apple");
orderedSet.add("Banana");
orderedSet.add("Cherry");
orderedSet.add("Banana"); // Banana 已经存在,所以这个调用不会改变集合
// 集合中的元素将按照插入顺序排列
System.out.println("LinkedHashSet: " + orderedSet);
// 向集合中添加一个新元素
orderedSet.add("Date");
// 打印更新后的集合,可以看到 Date 被添加到了最后
System.out.println("Updated LinkedHashSet: " + orderedSet);
}
}
输出将如下所示:
LinkedHashSet: [Apple, Banana, Cherry]
Updated LinkedHashSet: [Apple, Banana, Cherry, Date]
如你所见,尽管尝试添加了重复的 "Banana",但 LinkedHashSet
只保存了一个 "Banana" 实例,并且集合中的元素按照它们被插入的顺序列出。
-
HashSet和TreeSet的插入顺序:
HashSet
和 TreeSet
在 Java 中都是 Set
接口的实现,它们都保证了集合中元素的唯一性,但是它们存储和检索元素的方式不同,这影响了元素的顺序:
-
HashSet:
HashSet
是基于哈希表的数据结构。它使用哈希函数将元素映射到哈希表中的特定位置。由于哈希函数的结果可能相同(哈希冲突),HashSet
使用链表或平衡树等数据结构解决冲突,但这并不意味着元素会按照插入顺序保存。因此,HashSet
中元素的顺序是不确定的,通常与元素的哈希值和哈希表的内部结构有关。也就是说,HashSet
不保证元素的任何特定顺序,无论是插入顺序还是其他顺序。 -
TreeSet:
相比之下,TreeSet
是基于红黑树的数据结构。它会根据元素的自然顺序(通过Comparable
接口)或者用户提供的比较器(通过Comparator
接口)对元素进行排序。因此,TreeSet
中的元素总是按照某种顺序排列的,这个顺序取决于元素的比较方式。当你向TreeSet
中添加元素时,元素会被插入到适当的位置以保持树的排序属性。这意味着TreeSet
不会保留元素的插入顺序,而是按照排序规则自动调整元素的位置。
总结来说:
- 如果你需要一个快速的、元素唯一的集合,而且元素的顺序无关紧要,那么你应该选择
HashSet
。 - 如果你需要一个元素唯一的集合,并且这些元素必须按照一定的顺序(通常是自然顺序或定义的顺序)排列,那么你应该选择
TreeSet
。
如果你想保留元素的插入顺序,你可以使用 LinkedHashSet
,它是 HashSet
的子类,使用链表链接所有的节点,从而在保持元素唯一性的同时,也保留了元素的插入顺序。