220. 存在重复元素 III
- 原题链接:
- 完成情况:
- 解题思路:
- TreeSet
- sequenceSet.ceiling
- java中的红黑树
- 参考代码:
原题链接:
220. 存在重复元素 III
https://leetcode.cn/problems/contains-duplicate-iii/description/
完成情况:
解题思路:
TreeSet
TreeSet
在Java中,TreeSet是Java集合框架中的一种实现类,它继承自AbstractSet类并实现了NavigableSet接口。TreeSet是一个有序的集合,它根据元素的自然顺序或者通过Comparator进行排序。
以下是TreeSet的主要特点:
-
有序性:TreeSet中的元素是有序的。默认情况下,元素按照它们的自然顺序进行排序。如果元素是自定义对象,可以通过Comparator接口实现自定义的排序方式。
-
不允许重复元素:TreeSet不允许插入重复的元素。如果试图插入一个已经存在的元素,插入操作将被忽略。
-
基于红黑树实现:TreeSet内部是通过红黑树(Red-Black Tree)数据结构来实现的。这使得查找、插入和删除操作的时间复杂度为O(log n)。
-
导航方法:TreeSet提供了一系列的导航方法,如获取第一个元素、最后一个元素、大于给定元素的最小元素、小于给定元素的最大元素等。
-
不支持null元素:TreeSet不支持存储null元素。如果试图插入null元素,将会抛出NullPointerException。
使用TreeSet时,元素必须实现Comparable接口(自然排序)或在创建TreeSet时提供Comparator来指定排序方式。
以下是使用TreeSet的简单示例:
import java.util.*;
public class TreeSetExample {
public static void main(String[] args) {
// 创建一个TreeSet来存储整数类型的元素
TreeSet<Integer> numbers = new TreeSet<>();
// 向TreeSet中添加元素
numbers.add(5);
numbers.add(2);
numbers.add(8);
numbers.add(1);
numbers.add(3);
// 打印TreeSet中的元素(有序)
System.out.println(numbers); // 输出:[1, 2, 3, 5, 8]
// 导航方法示例
System.out.println("First element: " + numbers.first()); // 输出:First element: 1
System.out.println("Last element: " + numbers.last()); // 输出:Last element: 8
System.out.println("Greater than 4: " + numbers.higher(4)); // 输出:Greater than 4: 5
System.out.println("Less than 3: " + numbers.lower(3)); // 输出:Less than 3: 2
}
}
总结:TreeSet是一个有序的集合,适用于需要元素按照自然顺序或自定义排序方式进行排序的场景。由于其底层使用红黑树,查找、插入和删除操作具有较好的性能。但需要注意,TreeSet不支持存储null元素。
sequenceSet.ceiling
在Java的TreeSet中,ceiling()
方法用于返回集合中大于或等于给定元素的最小元素。它是NavigableSet接口中定义的一个方法,TreeSet实现了该接口。
方法签名为:
E ceiling(E e)
其中,E是集合中的元素类型。参数e是作为参考的元素,方法将返回TreeSet中大于或等于该元素的最小元素。如果不存在这样的元素,则返回null。
示例:
import java.util.*;
public class TreeSetExample {
public static void main(String[] args) {
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(5);
numbers.add(10);
numbers.add(15);
numbers.add(20);
// 获取大于或等于8的最小元素
Integer result1 = numbers.ceiling(8);
System.out.println("Ceiling of 8: " + result1); // 输出:Ceiling of 8: 10
// 获取大于或等于15的最小元素
Integer result2 = numbers.ceiling(15);
System.out.println("Ceiling of 15: " + result2); // 输出:Ceiling of 15: 15
// 获取大于或等于25的最小元素(不存在)
Integer result3 = numbers.ceiling(25);
System.out.println("Ceiling of 25: " + result3); // 输出:Ceiling of 25: null
}
}
在示例中,ceiling(8)
返回的结果是10,因为集合中大于或等于8的最小元素是10。ceiling(15)
返回的结果是15,因为15本身就是集合中的一个元素。而ceiling(25)
返回的结果是null,因为集合中没有大于或等于25的元素。
java中的红黑树
红黑树(Red-Black Tree)是一种自平衡二叉查找树,它在每个节点上都增加了一个额外的存储位来表示节点的颜色,可以是红色或黑色。这个颜色规则以及其他一些性质使得红黑树保持平衡,从而保证了查找、插入和删除操作的时间复杂度为 O(log n),其中 n 是树中节点的数量。
红黑树具有以下特性:
- 节点颜色:每个节点都是红色或黑色。
- 根节点和叶子节点:根节点是黑色的,叶子节点(空节点)是黑色的。叶子节点不存储数据,仅用于简化代码逻辑。
- 红色节点规则:红色节点的子节点必须是黑色的。
- 路径规则:从任意节点到其每个叶子节点的所有路径都包含相同数量的黑色节点。这个性质保证了树的平衡性。
- 插入规则:新插入的节点必须是红色的。然后,通过重新着色和旋转等操作来保持红黑树的性质。
红黑树的平衡性质保证了树的高度始终保持在 O(log n) 的范围内,因此查找、插入和删除等操作都可以在对数时间内完成,这使得红黑树在各种场景中都有广泛的应用。
在 Java 中,红黑树被广泛用于实现 TreeMap
和 TreeSet
。这些集合类在内部使用红黑树来维护有序性,并提供了高效的插入、删除和查找操作。
需要注意的是,红黑树虽然可以保持相对平衡,但并不是完美平衡的。因此,在某些情况下,其性能可能比平衡二叉搜索树(如 AVL 树)略差。但由于红黑树的平衡调整操作较为简单,所以通常在实践中更受欢迎。
参考代码:
package 中等题;
import java.util.TreeSet;
public class __220存在重复元素III__滑动窗口_有序集合 {
public boolean containsNearbyAlmostDuplicate(int[] nums, int indexDiff, int valueDiff){
int n = nums.length;
//-109 <= nums[i] <= 109
TreeSet<Long> sequenceSet = new TreeSet<Long>();
for (int i=0;i<n;i++){
Long ceiling = sequenceSet.ceiling((long) (nums[i] - (long)valueDiff));
if (ceiling != null && ceiling <= (long) nums[i] + (long)valueDiff){
return true;
}
sequenceSet.add((long) nums[i]);
if ( i >= indexDiff){
sequenceSet.remove((long)nums[i-indexDiff]);
}
}
return false;
}
}