剑指Offer-数据结构 30. 包含 min 函数的栈
Q:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 。
示例:
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 次
这个题目如果只是单纯的实现一个栈的pop,top,min都比较简单,但是这里要求时间复杂度是。
我们普通的实现就需要遍历一遍查找最小的元素,时间复杂度必然就到了.这里可以采用和之前用2个栈实现队列的方法来实现,用一个栈有序存入数据,则取得时候直接取该栈顶元素就是最小的,push元素到A栈的时候和A栈中的元素对比,如果小于A中的元素就同时push到B栈中,top直接取A栈顶元素,pop的时候需要判断同时移除A和B中的该元素。
typedef int STACK_TYPE;
/***************************************************
* Stack Operation
***************************************************/
typedef struct STACK_NODE {
STACK_TYPE value;
struct STACK_NODE *next;
}StackNode;
//destory stack
void destory(StackNode **stack) {
while(!is_empty(*stack)) {
pop(stack);
}
}
//push
void push(StackNode **stack, STACK_TYPE value) {
StackNode *new_node = (StackNode *)malloc(sizeof(StackNode));
assert(new_node != NULL);
//insert the new node into head
new_node->next = *stack;
new_node->value = value;
*stack = new_node;
}
//pop
void pop(StackNode **stack) {
StackNode *head;
assert(!is_empty(*stack));
head = *stack;
*stack = head->next;
free(head);
}
//top
STACK_TYPE top(const StackNode *const stack) {
assert(!is_empty(stack));
return stack->value;
}
//is_empty
int is_empty(const StackNode * const stack) {
return stack == NULL;
}
//never full
int is_full(const StackNode * const stack) {
return FALSE;
}
void demo_push(StackNode **stack_a, StackNode **stack_b,STACK_TYPE value) {
push(stack_a, value);
//栈B是栈A的非严格降序
if(is_empty(*stack_b) || value <= top(*stack_b)) {
push(stack_b, value);
}
}
void demo_pop(StackNode **stack_a, StackNode **stack_b) {
if(top(*stack_a) == top(*stack_b)) {
pop(stack_b);
}
pop(stack_a);
}
STACK_TYPE demo_top(const StackNode * const stack) {
return top(stack);
}
STACK_TYPE demo_min_top(const StackNode * const stack) {
return top(stack);
}
void display_stack(const StackNode * const stack) {
StackNode *p = stack;
while(p != NULL) {
printf(" %d ", p->value);
p = p->next;
}
}
/***************************************************
* Main
***************************************************/
int main() {
static StackNode *stack_a;
static StackNode *stack_b;
printf("push : 6\n");
demo_push(&stack_a, &stack_b, 6);
printf("push : 8\n");
demo_push(&stack_a, &stack_b, 8);
printf("push : 2\n");
demo_push(&stack_a, &stack_b, 2);
printf("push : 4\n");
demo_push(&stack_a, &stack_b, 4);
printf("stack_a: ");
display_stack(stack_a);
printf("\n");
printf("stack_b: ");
display_stack(stack_b);
printf("\n");
printf("top: %d\n", demo_top(stack_a));
printf("min_top: %d\n", demo_min_top(stack_b));
printf("pop...\n");
demo_pop(&stack_a, &stack_b);
printf("top: %d\n", demo_top(stack_a));
printf("min_top: %d\n", demo_min_top(stack_b));
printf("stack_a: ");
display_stack(stack_a);
printf("\n");
printf("stack_b: ");
display_stack(stack_b);
printf("\n");
destory(&stack_a);
destory(&stack_b);
return 0;
}
小结:
这个题目主要考察对栈的实现和对算法效率时间复杂度的理解,如何保证高效的栈操作,这个用双栈实现一些对栈顺序有所要求的操作技巧需要掌握,可能面试中会遇到。