堆栈LIFO
传统堆栈:
push:把一个新值压入到堆栈的顶部。
pop:把顶部元素从堆栈中移除,并且不返回这个值。
top:返回顶部元素的值,但不进行移除。
堆栈的实现:
- 静态数组堆栈
- 动态数组堆栈
- 链式堆栈
155. 最小栈
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) —— 将元素 x 推入栈中。
pop() —— 删除栈顶的元素。
top() —— 获取栈顶元素。
getMin() —— 检索栈中的最小元素。
示例:
输入:
[“MinStack”,“push”,“push”,“push”,“getMin”,“pop”,“top”,“getMin”]
[[],[-2],[0],[-3],[],[],[],[]]
输出:
[null,null,null,null,-3,null,0,-2]
解释:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.getMin(); --> 返回 -2.
解法:链式栈
#define MAXSIZE 1000
typedef struct {
int *data;
int top;
} MinStack; //创建结点
/** initialize your data structure here. */
MinStack* minStackCreate() {
MinStack *obj = (MinStack *)malloc(sizeof(MinStack));
obj->data = (int *)malloc(sizeof(int)*MAXSIZE);
obj->top = -1;
return obj;
} // 创建栈
void minStackPush(MinStack* obj, int x) {
if(obj->top == MAXSIZE-1) {}
else {
obj->top++;
obj->data[obj->top] = x;
}
} //入栈
void minStackPop(MinStack* obj) {
if(obj->top == -1) {}
else{
obj->top--;
}
} //出栈
int minStackTop(MinStack* obj) {
if(obj->top == -1) {
return NULL;
}
else {
return obj->data[obj->top];
}
} //获得栈顶元素
int minStackGetMin(MinStack* obj) {
if(obj->top == -1) {
return NULL;
}
if(obj->top == 0) {
return obj->data[0];
}
int min = obj->data[0];
for(int i = 0; i <= obj->top; i++) {
if(obj->data[i] < min) {
min = obj->data[i];
}
}
return min;
} //获得最小元素
void minStackFree(MinStack* obj) {
free(obj->data);
obj->data = NULL;
free(obj);
obj = NULL;
} //释放
/**
* Your MinStack struct will be instantiated and called as such:
* MinStack* obj = minStackCreate();
* minStackPush(obj, x);
* minStackPop(obj);
* int param_3 = minStackTop(obj);
* int param_4 = minStackGetMin(obj);
* minStackFree(obj);
*/
239. 滑动窗口最大值
给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 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
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sliding-window-maximum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
方法一:暴力破解法(超时)
int* maxSlidingWindow(int* nums, int numsSize, int k, int* returnSize){
if (nums == NULL || returnSize == NULL) {
return NULL;
}
int i, j;
int *output = (int *)malloc(sizeof(int)*(numsSize-k+1));
for (i = 0; i < numsSize-k+1; i++) {
int max = nums[i];
for(j = i; j < i+k; j++) {
if(nums[j] > max) {max = nums[j];}
}
output[i] = max;
*returnSize = numsSize-k+1;
}
return output;
}
方法二:双向队列
保存当前窗口最大值的数组位置(最左边为最大值) 队列中数组位置的数值按从大到小排序
int* maxSlidingWindow(int* nums, int numsSize, int k, int* returnSize){
int *output = (int *)malloc(sizeof(int) * (numsSize-k+1));
*returnSize = numsSize-k+1; //返回数组大小
int *queue = (int *)malloc(sizeof(int)*numsSize); // 队列
int front = 0 , rear = 0;
for(int i = 0; i < numsSize; i++) {
while(front != rear && nums[queue[rear - 1]] < nums[i]) {rear--;} // 队尾元素 < 未入队元素 , 弹出队尾元素
queue[rear++] = i; // 新元素入队
if(i >= k-1) {
output[i-k+1] = nums[queue[front]]; // 当前窗口最大值加入结果
if(front != rear && queue[front] <= i-k+1) {front++;} // 队头元素出窗(出队)
} // 开始滑动窗口
}
free(queue); //释放队列
return output;
}