问题描述
我正在做一些简单的算法问题并尝试使用 arraydeque。
例如这个:
https://leetcode.com/problems/maximum-depth-of-binary-tree/submissions/
在使用 BFS 时,我注意到 offerLast & pollFirst / offerFirst & pollLast 都给出了相同(正确)的答案。
是否有关于何时使用哪个的最佳实践?由于这应该是一个队列,我认为我们应该提供最后并使用 pollFirst。但是为什么 offerFirst / pollLast 也能用呢?
public int maxDepth(TreeNode root) {
// do BFS
if (root == null) return 0;
int depth = 0;
arraydeque<TreeNode> queue = new arraydeque();
queue.offerLast(root);
while(!queue.isEmpty()){
int size = queue.size();
for (int i = 0; i < size; i++){
TreeNode curr = queue.pollFirst();
if (curr.left != null) queue.offerLast(curr.left);
if (curr.right != null) queue.offerLast(curr.right);
}
depth++;
}
return depth;
}
另外,我知道我们不需要队列为 arraydeque 类型。只是一个简单的队列就可以工作,队列只提供默认为先进先出实现(offerLast,pollFirst)的报价/轮询
解决方法
但是为什么 offerFirst / pollLast 也可以工作?
因为队列的“开始”和“结束”实际上只是随意决定的。
您可以将第一个元素称为“开始”,将最后一个元素称为“结束”。在这种情况下,offerLast
入队,pollFirst
出队。
由于数组双端队列是线性数据结构,您可以“翻转它”并说,我将第一个元素称为队列的“结束”,将最后一个元素称为队列的“开始”。如果您这样想,那么您将通过调用 offerFirst
入队并通过 pollLast
出队。
解释这一点的另一种方法是表明这只是两种观点:
假设我们站在双端队列的两端。我们都认为离我们最近的元素是双端队列的“第一个元素”。
the deque;
a b c d e f g h
^ ^
| |
you me
您在 a
旁边放置了一个新元素。从您的角度来看,这是 offerFirst
。从我的角度来看,你会做offerLast
!
现在假设您删除了 h
。从您的角度来看,这是 pollLast
。从我的角度来看,这看起来像 pollFirst
- 您正在删除“最后一个元素”,但它是我的“第一个元素”。
但是,请注意,官方决定第一个元素是队列的开头,最后一个元素是结尾——这就是ArrayDeque
实现Queue
接口的方式——所以如果你从 Queue
调用方法,比如 offer
,它会调用 offerLast
。
虽然如果你有自己的开始和结束的概念它仍然有效,但遵循“开始”和“结束”的官方定义仍然是一个好习惯(实际上只需使用offer
和{{1 }}!)。如果您使用 poll
和 pollLast
,如果您将双端队列传递给另一段需要 offerFirst
的代码,您的代码可能无法工作。