剑指 offer
剑指 Offer 09. 用两个栈实现队列
难度 : 简单
题目 :
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数
appendTail
和deleteHead
,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead
操作返回 -1 )
示例 1:
输入:
["CQueue","appendTail","deleteHead","deleteHead"]
[[],[3],[],[]]
输出:[null,null,3,-1]
示例 2:
输入:
["CQueue","deleteHead","appendTail","appendTail","deleteHead","deleteHead"]
[[],[],[5],[2],[],[]]
输出:[null,-1,null,null,5,2]
提示:
1 <= values <= 10000
最多会对 appendTail、deleteHead 进行 10000 次调用
大致思路:
使用两个栈来实现队列的操作,队列的操作是先进先出,而栈的操作是先进后出。 因此通过两个栈实现队列的做法是, 一个栈作为输入栈,用于存放队列入队的数据;另一个栈作为输出栈,用于存放队列的出队的数据。先入队的数据先压入输入栈, 出队的数据则将输入栈的全部数据依次弹出并压入到输出栈中, 这样从输出栈输出的数据就是队列从队首往队尾的顺序。
实现语言 : Java
官方做法:
class CQueue {
Deque<Integer> stackIn;
Deque<Integer> stackOut;
public CQueue() {
stackIn = new ArrayDeque<Integer>();
stackOut = new ArrayDeque<Integer>();
}
public void appendTail(int value) {
stackIn.push(value);
}
public int deleteHead() {
if (stackOut.isEmpty()){
if(stackIn.isEmpty()){
return -1;
}
while(!stackIn.isEmpty()){
stackOut.push(stackIn.pop());
}
}
return stackOut.pop();
}
}
C语言实现:
个人实现
typedef struct ST{
int value;
struct ST *next;
}Stack;
typedef struct {
Stack stackIn;
Stack stackOut;
} CQueue;
CQueue* cQueueCreate() {
CQueue* queue = (CQueue *)malloc(sizeof(CQueue));
queue->stackIn.next = NULL;
queue->stackOut.next = NULL;
return queue;
}
void cQueueAppendTail(CQueue* obj, int value) {
Stack *L = (Stack *)malloc(sizeof(Stack));
L->next = obj->stackIn.next;
L->value = value;
obj->stackIn.next = L;
//使用头插法来插入链表
}
int cQueueDeleteHead(CQueue* obj) {
int bottom = -1;
if (obj->stackOut.next == NULL){
if (obj->stackIn.next == NULL)
return -1;
Stack *p = obj->stackIn.next;
while(p!=NULL){
Stack *s = (Stack *)malloc(sizeof(Stack));
s->value=p->value;
s->next = obj->stackOut.next;
obj->stackOut.next = s;
p = p->next;
}
obj->stackIn.next=NULL;
}
int top =obj->stackOut.next->value;
obj->stackOut.next = obj->stackOut.next->next;
return top;
}
void cQueueFree(CQueue* obj) {
free(obj);
}
剑指 Offer 30. 包含min函数的栈
难度 : 简单
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
示例:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.min(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.min(); --> 返回 -2.
提示: 各函数的调用总次数不超过 20000 次
—-
大致思路: 使用两个栈来实现,,一个数据存放栈来存放压入栈中的数据, 另个最小元素栈来存放当前数据栈内最小的元素, 当调用min方法时读取最小元素栈的栈顶元素。数据栈每次进一个元素的同时也把数据栈内最小元素值放入最小元素栈中, 出栈时, 两个栈同时出栈顶元素。
官方描述:按照上面的思路,我们只需要设计一个数据结构,使得每个元素 a 与其相应的最小值 m 时刻保持一一对应。因此我们可以使用一个辅助栈,与元素栈同步插入与删除,用于存储与每个元素对应的最小值。当一个元素要入栈时,我们取当前辅助栈的栈顶存储的最小值,与当前元素比较得出最小值,将这个最小值插入辅助栈中;当一个元素要出栈时,我们把辅助栈的栈顶元素也一并弹出;在任意一个时刻,栈内元素的最小值就存储在辅助栈的栈顶元素中。
- java实现
官方解法:
class MinStack {
Deque<Integer> nStack;
Deque<Integer> minStack;
public MinStack() {
nStack = new LinkedList<Integer>();
minStack = new LinkedList<Integer>();
minStack.push(Integer.MAX_VALUE); //存放最小数的栈中先存放一个Integer类型中的最大整数, 主要是第一次在与栈内元素比较时, 无论多大值都会当成最小值处理
}
public void push(int x) {
nStack.push(x);
minStack.push(Math.min(minStack.getFirst(), x));
}
public void pop() {
nStack.pop();
minStack.pop();
}
public int top() {
return nStack.getFirst(); //拿出栈顶元素
}
public int min() {
return minStack.getFirst(); //拿出栈顶元素
}
}
个人实现
class MinStack {
Deque<Integer> nStack;
Deque<Integer> minStack;
public MinStack() {
nStack = new LinkedList<Integer>();
minStack = new LinkedList<Integer>();
}
public void push(int x) {
nStack.push(x);
try{
minStack.push(Math.min(minStack.getFirst(), x)); //当栈为空时, getFirst会报错, 则直接将执行下一句
}catch(Exception e){
minStack.push(x);
}
}
public void pop() {
nStack.pop();
minStack.pop();
}
public int top() {
return nStack.getFirst(); //拿出栈顶元素
}
public int min() {
return minStack.getFirst(); //拿出栈顶元素
}
}
C语言实现:
个人实现
typedef struct MS{
int min;
struct MS *next;
} MinStack;
/** initialize your data structure here. */
MinStack* minStackCreate() {
MinStack* m = (MinStack *)malloc(sizeof(MinStack));
m->next = NULL;
return m;
}
void minStackPush(MinStack* obj, int x) {
MinStack* new1 = (MinStack*)malloc(sizeof(MinStack));
MinStack* new2 = (MinStack*)malloc(sizeof(MinStack));
if (obj->next == NULL){
new1 -> min = x;
new1 ->next = obj->next;
obj->next = new1;
}else{
int t = obj->next->next->min;
new1 -> min = t>x?x:t;
new1 ->next = obj->next;
obj->next = new1;
}
new2 -> min = x;
new2 ->next = obj->next;
obj->next = new2;
}
void minStackPop(MinStack* obj) {
obj->next = obj->next->next->next;
}
int minStackTop(MinStack* obj) {
return obj->next->min;
}
int minStackMin(MinStack* obj) {
return obj->next->next->min;
}
void minStackFree(MinStack* obj) {
free(obj);
}