LeetCode 232. Implement Queue using Stacks
题意
使用栈实现队列的下列操作:
- push(x) -- 将一个元素放入队列的尾部。
- pop() -- 从队列首部移除元素。
- peek() -- 返回队列首部的元素。
- empty() -- 返回队列是否为空。
- 说明:
- 你只能使用标准的栈操作 -- 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
- 你所使用的语言也许不支持栈。你可以使用 list 或者 deque (双端队列) 来模拟一个栈,只要是标准的栈操作即可。
- 假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)。
题解
- 使用两个栈,一个用于存储数据,一个用于辅助操作
- push 操作时,将数据压入数据栈
- pop 操作时,将数据栈中的数据依次弹出并压入辅助栈,弹出辅助栈的栈顶元素,再将辅助栈中的数据依次弹出并压入数据栈
- peek 操作时,将数据栈中的数据依次弹出并压入辅助栈,弹出辅助栈的栈顶元素,再将辅助栈中的数据依次弹出并压入数据栈
- empty 操作时,判断数据栈是否为空
- 时间复杂度:O(n),空间复杂度:O(n)
代码
class MyQueue:
def __init__(self):
"""
Initialize your data structure here.
"""
self.data = []
self.helper = []
def push(self, x: int) -> None:
"""
Push element x to the back of queue.
"""
self.data.append(x)
def pop(self) -> int:
"""
Removes the element from in front of queue and returns that element.
"""
while self.data:
self.helper.append(self.data.pop())
res = self.helper.pop()
while self.helper:
self.data.append(self.helper.pop())
return res
def peek(self) -> int:
"""
Get the front element.
"""
while self.data:
self.helper.append(self.data.pop())
res = self.helper[-1]
while self.helper:
self.data.append(self.helper.pop())
return res
def empty(self) -> bool:
"""
Returns whether the queue is empty.
"""
return not self.data
java
class MyQueue {
private Stack<Integer> data;
private Stack<Integer> helper;
/** Initialize your data structure here. */
public MyQueue() {
data = new Stack<>();
helper = new Stack<>();
}
/** Push element x to the back of queue. */
public void push(int x) {
data.push(x);
}
/** Removes the element from in front of queue and returns that element. */
public int pop() {
while (!data.isEmpty()) {
helper.push(data.pop());
}
int res = helper.pop();
while (!helper.isEmpty()) {
data.push(helper.pop());
}
return res;
}
/** Get the front element. */
public int peek() {
while (!data.isEmpty()) {
helper.push(data.pop());
}
int res = helper.peek();
while (!helper.isEmpty()) {
data.push(helper.pop());
}
return res;
}
/** Returns whether the queue is empty. */
public boolean empty() {
return data.isEmpty();
}
}
LeetCode239 滑动窗口最大值
题意
给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。
示例:
输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值
--------------- -----
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
提示:
你可以假设 k 总是有效的,在输入数组不为空的情况下,1 ≤ k ≤ 输入数组的大小。
题解
- 使用双端队列,队列中存储的是数组的下标
- 遍历数组,如果队列不为空且队列中的最大值小于当前值,则将队列中的最大值弹出
- 将当前值压入队列
- 如果队列中的最大值的下标小于等于当前下标减去窗口大小,则将队列中的最大值弹出
- 如果当前下标大于等于窗口大小减一,则将队列中的最大值压入结果数组
- 时间复杂度:O(n),空间复杂度:O(k)
代码
python
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
if not nums:
return []
res = []
queue = []
for i in range(len(nums)):
if queue and nums[queue[-1]] < nums[i]:
queue.pop()
queue.append(i)
if queue[0] <= i - k:
queue.pop(0)
if i >= k - 1:
res.append(nums[queue[0]])
return res
java
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if (nums == null || nums.length == 0) {
return new int[0];
}
int[] res = new int[nums.length - k + 1];
Deque<Integer> queue = new LinkedList<>();
for (int i = 0; i < nums.length; i++) {
if (!queue.isEmpty() && nums[queue.peekLast()] < nums[i]) {
queue.pollLast();
}
queue.offerLast(i);
if (queue.peekFirst() <= i - k) {
queue.pollFirst();
}
if (i >= k - 1) {
res[i - k + 1] = nums[queue.peekFirst()];
}
}
return res;
}
}