1.
设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。
你的实现应该支持如下操作:
MyCircularQueue(k)
: 构造器,设置队列长度为 k 。Front
: 从队首获取元素。如果队列为空,返回 -1 。Rear
: 获取队尾元素。如果队列为空,返回 -1 。enQueue(value)
: 向循环队列插入一个元素。如果成功插入则返回真。deQueue()
: 从循环队列中删除一个元素。如果成功删除则返回真。isEmpty()
: 检查循环队列是否为空。isFull()
: 检查循环队列是否已满。
可以用数组实现这个循环队列.
每进行一次入队操作,deal就向后移动一次,rear指向下一次入队的位置.front指向出队的位置.假如说
rear走到了位置3,还可以继续走下一个位置是0,那么只要rear和frontbu不相遇就可以一直进行入队和出队操作.即构成了循环队列,具体代码如下:
public class MyCircularQueue {
/*MyCircularQueue(k): 构造器,设置队列长度为 k 。
Front: 从队首获取元素。如果队列为空,返回 -1 。
Rear: 获取队尾元素。如果队列为空,返回 -1 。
enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
isEmpty(): 检查循环队列是否为空。
isFull(): 检查循环队列是否已满
*/
public int[] elem;
int front=0;
int rear=0;
public MyCircularQueue(int k) {
elem=new int[k+1];
}
public boolean enQueue(int value) {
//首先判断循环队列是否是满
if(isFull()){
return false;
}
//在rear位置插入
elem[rear]=value;
rear=(rear+1)%elem.length;
return true;
}
public boolean deQueue() {
//删除和插入应该是同一个逻辑
//首先判断这个队列是否是空
if(isEmpty()){
return false;
}
//直接让front后移即可
front=(front+1)%elem.length;
return true;
}
public int Front() {
//先判断是否是空
if(isEmpty()){
return -1;
}
//不是空,返回front指向的即可
return elem[front];
}
public int Rear() {
if(isEmpty()){
return -1;
}
int index=(rear==0?rear+elem.length-1:rear-1);
return elem[index];
}
public boolean isEmpty() {
return front==rear;
}
public boolean isFull() {
//这里采用牺牲一个空间的做法来实现这个循环队列
return (rear+1)%elem.length==front;
}
}
2.用队列实现栈
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push
、top
、pop
和 empty
)。
实现 MyStack
类:
void push(int x)
将元素 x 压入栈顶。int pop()
移除并返回栈顶元素。int top()
返回栈顶元素。boolean empty()
如果栈是空的,返回true
;否则,返回false
。
具体代码如下:
class MyStack {
Queue<Integer> t1;
Queue<Integer> t2;
public MyStack(){
t1=new LinkedList<>();
t2=new LinkedList<>();
}
public void push(int x) {
//因为第一次入站的时候,两个队列都可以使用,然后后面入栈的时候,就要不为空的队列中入队了,所以
//入栈的时候,可以看成总是向不为空的队列中入队
if(t1.isEmpty()){
//如果t1是空的队列,就向t2中入队.
t2.offer(x);
}else{
//反之,t1不是空,就想t1中入队.
t1.offer(x);
}
}
public int pop() {
//移除并返回栈顶元素.
//需要把有元素的队中的size-1个元素移动到没有元素的队列中去
//还是首先判断,那个是空哪个不是
if(t1.isEmpty()){
int size=t2.size();
//t1是空,就要把t2中的size-1个元素移动到t1中去
for(int i=0;i<size-1;i++){
//然后t1进行入队操作即可
t1.offer(t2.poll());
}
//现在t2里的最后一个元素就是要进行出战的
return t2.poll();
}else{
//t2使空,操作还是一样的,t1换成t2,t2换成t1即可.
int size=t1.size();
for(int i=0;i<size-1;i++){
//然后t2进行入队操作即可
t2.offer(t1.poll());
}
return t1.poll();
}
}
public int top() {
//int top() 返回栈顶元素。
//还是一样的,只不过不删除而已
if(t1.isEmpty()){
int tem=0;
int size=t2.size();
//t1是空,就要把t2中的size-1个元素移动到t1中去
for(int i=0;i<size;i++){
tem=t2.poll();
//然后t1进行入队操作即可
t1.offer(tem);
}
//现在t2里的最后一个元素就是要进行出战的
return tem;
}else{
//t2使空,操作还是一样的,t1换成t2,t2换成t1即可.
int size=t1.size();
int tem=0;
for(int i=0;i<size;i++){
tem=t1.poll();
//然后t2进行入队操作即可
t2.offer(tem);
}
return tem;
}
}
public boolean empty() {
if(t1.isEmpty()&&t2.isEmpty()){
return true;
}else{
return false;
}
}
}
3.
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push
、pop
、peek
、empty
):
实现 MyQueue
类:
void push(int x)
将元素 x 推到队列的末尾int pop()
从队列的开头移除并返回元素int peek()
返回队列开头的元素boolean empty()
如果队列为空,返回true
;否则,返回false
class MyQueue {
Stack<Integer> t1;
Stack<Integer> t2;
public MyQueue() {
t1=new Stack<>();
t2=new Stack<>();
}
public void push(int x) {
//假设入队操作都在t1中进行.
t1.push(x);
}
public int pop() {
if(t2.isEmpty()){
int size=t1.size();
for(int i=0;i<size;i++){
t2.push(t1.pop());
}
return t2.pop();
}else{
return t2.pop();
}
}
public int peek() {
if(t2.isEmpty()){
int size=t1.size();
for(int i=0;i<size;i++){
t2.push(t1.pop());
}
return t2.peek();
}else{
return t2.peek();
}
}
public boolean empty() {
return t1.isEmpty()&&t2.isEmpty();
}
}