算法之集合与容器篇
HashMap
常用操作
- 初始化 (
HashMap<KeyType, ValueType> map
): 创建一个空的HashMap。 - 插入元素 (
map.put(key, value)
): 将一个新的键值对插入到HashMap中。如果键已经存在,则更新其对应的值。 - 获取元素 (
map.get(key)
): 根据键来获取对应的值。如果HashMap中不存在这个键,则返回null
。 - 检查存在 (
map.containsKey(key)
): 检查HashMap中是否存在指定的键。返回一个布尔值。 - 删除元素 (
map.remove(key)
): 根据键来删除HashMap中的一个元素。 - 遍历:
- 遍历键 (
for (KeyType key : map.keySet())
): 遍历HashMap中的所有键。 - 遍历值 (
for (ValueType value : map.values())
): 遍历HashMap中的所有值。 - 遍历键值对 (
for (Map.Entry<KeyType, ValueType> entry : map.entrySet())
): 同时遍历键和值。
- 遍历键 (
- 获取大小 (
map.size()
): 返回HashMap中键值对的数量。 - 清空HashMap (
map.clear()
): 删除HashMap中的所有元素。
使用场景
HashMap经常用于反转数组下标和下标对应的值,根据值来搜索下标。
HashMap也可以用来减少查找元素的时间复杂度,如果每次都要遍历查找元素,那么使用HashMap将会大幅压缩时间。
HashMap还用于储存键值对,例如字符及其在字符串中的位置。
在DFS或者BFS的图论中,HashMap还可以表示一个元素有没有被访问。
HashSet
常用操作(其实和Map差不多)
- 初始化 (
HashSet<Type> hashSet = new HashSet<>();
): 创建一个新的空HashSet
。 - 添加元素(就这里不一样)
hashSet.add(element)
: 如果HashSet
中还没有该元素,则添加该元素。
- 删除元素
hashSet.remove(element)
: 移除指定的元素。
- 检查元素
hashSet.contains(element)
: 检查HashSet
中是否包含指定的元素。
- 集合大小
hashSet.size()
: 返回HashSet
中的元素数量。
- 清空集合
hashSet.clear()
: 移除HashSet
中的所有元素。
- 空检查
hashSet.isEmpty()
: 检查HashSet
是否为空。
- 遍历
- 可以通过 for-each 循环遍历
HashSet
中的元素。
- 可以通过 for-each 循环遍历
使用场景
Set和Map的区别是,Set的元素不可以重复,这也是Set最大的特点,一般用于去重然后快速查询元素,很好使。
Set还可以快速判断元素是否存在于集合当中,在一些场景下可以中断元素重复引起id循环,比如快乐数。
LinkedList
常用操作
- 初始化 (
LinkedList<Type> linkedList = new LinkedList<>();
): 创建一个新的空 LinkedList。 - 添加元素
linkedList.add(element)
: 在链表尾部添加一个元素。linkedList.addFirst(element)
: 在链表头部添加一个元素。linkedList.addLast(element)
: 在链表尾部添加一个元素(同add
)。linkedList.add(index, element)
: 在指定位置添加一个元素。
- 访问元素
linkedList.get(index)
: 获取指定位置的元素。linkedList.getFirst()
: 获取链表的第一个元素。linkedList.getLast()
: 获取链表的最后一个元素。
- 修改元素
linkedList.set(index, element)
: 替换指定位置的元素。
- 删除元素
linkedList.remove()
: 移除并返回链表的第一个元素。linkedList.remove(index)
: 移除指定位置的元素。linkedList.removeFirst()
: 移除并返回链表的第一个元素。linkedList.removeLast()
: 移除并返回链表的最后一个元素。
- 检查元素
linkedList.contains(element)
: 检查链表是否包含指定的元素。linkedList.size()
: 返回链表中的元素数量。
- 遍历
- 可以通过 for-each 循环或迭代器进行遍历。
使用场景
链表是一个大类的题目,本质上考察的还是链表的基本操作,很多操作涉及双指针,例如反转链表,旋转链表、回文链表、环形链表等等。
理解链表是双向的,底层是由链表节点和指针维护的就行,可以双向操作。
ArrayList
常用操作
- 初始化 (
ArrayList 或者 List<Type> list = new ArrayList<>();
): 创建一个空的ArrayList
。 - 添加元素
list.add(element)
: 在列表末尾添加一个元素。list.add(index, element)
: 在指定位置插入一个元素。
- 访问元素 (
list.get(index)
): 返回列表中指定位置的元素。 - 修改元素 (
list.set(index, element)
): 替换指定位置的元素。 - 删除元素
list.remove(index)
: 移除指定位置的元素。list.remove(Object o)
: 移除第一个出现的指定元素。
- 大小和清空
list.size()
: 返回列表中的元素数。list.clear()
: 移除列表中的所有元素。
- 检查和搜索
list.contains(Object o)
: 检查列表中是否存在指定的元素。list.indexOf(Object o)
: 返回指定元素的索引,如果不存在,则返回 -1。
- 遍历
- 使用
for
循环或for-each
循环遍历ArrayList
中的元素。
- 使用
使用场景
ArrayList的使用场景还是比较单一的,需要返回一个数组,但不知道数组的大小,就可以使用这个多态数组。
广泛用于回溯,储存中间的结果。
Queue
常用操作
- 初始化 (
Queue<Type> queue = new LinkedList<>();
): 创建一个空的Queue
实例。 - 添加元素
queue.offer(element)
: 将指定元素添加到此队列的尾部。queue.add(element)
: 将指定元素添加到此队列的尾部(与offer
相同,但在容量限制的队列中可能表现不同)。
- 访问元素
queue.peek()
: 获取但不移除此队列的头;如果此队列为空,则返回null
。queue.element()
: 获取但不移除此队列的头;如果此队列为空,则抛出异常。
- 删除元素
queue.poll()
: 获取并移除此队列的头;如果此队列为空,则返回null
。queue.remove()
: 获取并移除此队列的头;如果此队列为空,则抛出异常。
- 大小和清空
queue.size()
: 返回队列中的元素数。queue.clear()
: 移除队列中的所有元素。
- 检查
queue.isEmpty()
: 检查队列是否为空。
使用场景
Queue主要在BFS中被广泛使用,是BFS类算法的基石。
PriorityQueue(优先队列)
常用操作
-
初始化:
-
PriorityQueue<Type> priorityQueue = new PriorityQueue<>();
: 创建一个新的空PriorityQueue
,元素按自然顺序排序。 -
PriorityQueue<Type> priorityQueue = new PriorityQueue<>(Comparator.comparator);
: 创建一个新的空PriorityQueue
,按指定比较器排序。//最小堆 PriorityQueue<Integer> priorityQueue = new PriorityQueue<>((o1, o2) -> o1 - o2); //最大堆 PriorityQueue<Integer> priorityQueue = new PriorityQueue<>((o1, o2) -> o2 - o1);
-
-
添加元素:
priorityQueue.add(element)
: 添加一个元素到队列。priorityQueue.offer(element)
: 添加一个元素到队列,提供了另一种方式来添加元素。
-
访问元素:
priorityQueue.peek()
: 获取队列头部的元素,但不移除,如果队列为空,返回null
。
-
删除元素:
priorityQueue.poll()
: 移除并返回队列头部的元素,如果队列为空,返回null
。
-
队列大小:
priorityQueue.size()
: 返回队列中的元素数量。
-
清空队列:
priorityQueue.clear()
: 移除队列内所有元素。
-
空检查:
priorityQueue.isEmpty()
: 检查队列是否为空。
使用场景
PriorityQueue经常用于遍历中排序,也就是“找到最大/小的 xx个元素”。
Stack
常用操作
- 初始化 (
Stack<Type> stack = new Stack<>();
): 创建一个空的Stack
实例。 - 添加元素
stack.push(element)
: 将一个元素压入栈顶。
- 访问元素
stack.peek()
: 返回栈顶元素,但不从栈中移除它。
- 删除元素
stack.pop()
: 移除并返回栈顶元素。
- 大小和清空
stack.size()
: 返回栈中的元素数量。stack.clear()
: 移除栈内所有元素。
- 检查
stack.isEmpty()
: 检查栈是否为空。
使用场景
Stack是很基础的一种数据结构,可以用于解决**“对称”性的问题**。比如检查括号,逆波兰表达式等等。
Stack还可以用于解决单调计数的问题,下一个更大的元素,气温升高需要等待的天数,以及很经典的接雨水,本质都是单调递增或者递减区间的计数问题。
- PriorityQueue(优先队列)
- 应用场景:适用于需要元素有序访问的场景,比如求解数据流的中位数、合并K个排序链表等问题。它可以保证每次取出的是优先级最高(或最低)的元素。