单调栈
第一题
实现类就是typedef并用数组或int或其他类来实现这个类
typedef struct {
int stack[10000];
int stacktop;
int minstack[10000];
int minstacktop;
}MinStack;//辅助栈,栈顶存最小值;
MinStack* minStackCreate()
{
MinStack* newStack = (MinStack *) malloc(sizeof(MinStack));
newStack->stacktop = 0;
newStack->minstacktop = 0;
return newStack;
}
void minStackPush(MinStack* obj, int val) {
obj->stack[obj->stacktop++]=val;
if(obj->minstacktop==0||obj->minstack[obj->minstacktop-1]>=val)
{
obj->minstack[obj->minstacktop++]=val;
}
}
void minStackPop(MinStack* obj) {
if(obj->minstack[obj->minstacktop-1]==obj->stack[obj->stacktop-1])
{
obj->minstacktop--;
}
obj->stacktop--;
}
int minStackTop(MinStack* obj) {
return obj->stack[obj->stacktop-1];
}
int minStackGetMin(MinStack* obj) {
return obj->minstack[obj->minstacktop-1];
}
void minStackFree(MinStack* obj) {
free(obj);
}//obj是一个类,表示栈和辅助栈
知识点:
1.利用一个辅助栈来实现查找最小值,当push和pop时实时更新最小栈的顶端(最小值)
2.struct定义
typedef struct{
}minstack
第二题
运用单调栈思想,栈里的元素(下标)单调递减,在栈里的元素下标都是未配对成功的下标,正向遍历,与栈里的元素相比较,大于就将栈顶元素移除,并继续重复操作,直到栈为空或遍历的元素小于栈里元素(因为栈是单调递减的),然后将遍历元素进栈,
最后在栈里的元素都是最后ret数组里为0的,因为没找到匹配的。
int* dailyTemperatures(int* temperatures, int temperaturesSize, int* returnSize){
int stack[100001];
int top=0;
int *ret=(int*)malloc(sizeof(int)*temperaturesSize);
memset(ret, 0, sizeof(int) * temperaturesSize);
for(int i=0;i<temperaturesSize;i++)
{
while(top!=0&&temperatures[i]>temperatures[stack[top-1]])
{
int temp=stack[--top];
ret[temp]=i-temp;
}
stack[top++]=i;
}
*returnSize=temperaturesSize;
return ret;
}
记得出栈是--top,入栈是[top++]
栈模拟队列
第一题
先用线性表实现栈
typedef struct{
int*stack;
int stkcapicity;
int top;
}Stack;
Stack* stackcreate(int capicity)
{
Stack*ret=(Stack*)malloc(sizeof(Stack));//为创建一个stack类申请空间
ret->stkcapicity=capicity;
ret->top=0;
return ret;
}
void stackpush(Stack*obj,int x)
{
obj->stk[obj->top++]=x;
}
void stacktop(Stack*obj)
{
return obj->stk[obj->top-1];
}
bool stackempty(Stack*obj)
{
return obj->top==0;
}
void free(Stack*obj)
{
free(obj->stk);
}
MyStack*ret=malloc(sizeof(MyStack));
注意申请空间时要这么写
typedef struct{
// 栈
int *stack;
// 栈中元素个数
int stackSize;
// 栈的容量
int stackCapacity;
}MyStack;
MyStack* myStackCreate(int capacity){
// 分配内存空间
MyStack * myStack=malloc(sizeof(MyStack));
myStack->stack=malloc(sizeof(int)*capacity);
// 当前没有元素
myStack->stackSize=0;
// 栈容量
myStack->stackCapacity=capacity;
return myStack;
}
void mystackpush(MyStack*mystack,int val)
{
mystack->stack[mystack->stackSize++]=val;
}
void mystackpop(MyStack*mystack)
{
mystack->stackSize--;
}
int mystackpeek(MyStack*mystack)
{
return mystack->stack[mystack->stackSize-1];
}//获取栈顶元素
bool mystackempty(MyStack*mystack)
{
return mystack->stackSize==0;
}
void mystackfree(MyStack*mystack)
{
free(mystack->stack);
}
用栈实现队列
typedef struct {
MyStack*instack;//输入栈,所有push都进去
MyStack*outstack;//用两个栈实现队列
} MyQueue;
MyQueue* myQueueCreate() {
MyQueue*ret=malloc(sizeof(MyQueue));
ret->instack=myStackCreate(100);
ret->outstack=myStackCreate(100);
return ret;
}//为类申请空间,初始化类
void myQueuePush(MyQueue* obj, int x) {
mystackpush(obj->instack,x);
}
void in2out(MyQueue*obj)
{
while(!mystackempty(obj->instack))
{
mystackpush(obj->outstack,mystackpeek(obj->instack));
mystackpop(obj->instack);
}
}//将instack的都到outstack里
int myQueuePop(MyQueue* obj) {
if(mystackempty(obj->outstack))
{
in2out(obj);//outstack为空时,将instack的压入他
}
int x=mystackpeek(obj->outstack);
mystackpop(obj->outstack);
return x;
}//pop队列的队首元素,也就是栈的栈底元素,所以将instack里的都pop出来,push进outstack,当outstack非空时,队首元素只可能在outstack的栈顶,不可能在instack
int myQueuePeek(MyQueue* obj) {
if(mystackempty(obj->outstack))
{
in2out(obj);
}
int x=mystackpeek(obj->outstack);
return x;
}//队首元素只有两种情况,一种是只push还没有pop过的队列,这时outstack为空,队首元素在instack的栈底,用front记录,另一种情况是已经pop过了,那么outstack不为空,队首元素为outstack的栈顶
bool myQueueEmpty(MyQueue* obj) {
return mystackempty(obj->instack)&&mystackempty(obj->outstack);
}
void myQueueFree(MyQueue* obj) {
mystackfree(obj->instack);
mystackfree(obj->outstack);
}
注意申请空间时也要为stack申请空间
辅助栈
第一题
//维护前缀和数组(乘积)
typedef struct {
int zeroindex;
int top;
int a[40001];
} ProductOfNumbers;
ProductOfNumbers* productOfNumbersCreate() {
ProductOfNumbers*ret=(ProductOfNumbers*)malloc(sizeof(ProductOfNumbers));
ret->zeroindex=-1;
ret->top=0;
return ret;
}
void productOfNumbersAdd(ProductOfNumbers* obj, int num) {
obj->a[obj->top]=num;
if(num==0)
{
obj->a[obj->top]=1;
obj->zeroindex=obj->top;
}
else
{
obj->a[obj->top]=num*obj->a[obj->top-1];
}
(obj->top)++;
}
int productOfNumbersGetProduct(ProductOfNumbers* obj, int k) {
if(obj->zeroindex>obj->top-k-1)
{
return 0;//说明倒数k个有0
}
else{
return obj->a[obj->top-1]/obj->a[obj->top-1-k];
}
}
void productOfNumbersFree(ProductOfNumbers* obj) {
free(obj);
}
构造前缀和数组,记录top,zeroindex(最近的0的下标)
第二题
太难了,不像我能做出来的题
单调栈,栈里的元素的acii码单调递增
和之前的单调栈相同,如果遍历元素大于栈顶元素ascii码并且栈顶元素在之后还会出现(用哈希表记录lastindex实现),就逐个移除栈顶元素
如果栈里已经出现遍历元素,直接跳过(由bool visited【26】得到)
最大矩形
第一题
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int n = heights.size();
vector<int> left(n), right(n);
stack<int> mono_stack;
for (int i = 0; i < n; ++i) {
while (!mono_stack.empty() && heights[mono_stack.top()] >= heights[i]) {
mono_stack.pop();
}
left[i] = (mono_stack.empty() ? -1 : mono_stack.top());
mono_stack.push(i);
}
mono_stack = stack<int>();
for (int i = n - 1; i >= 0; --i) {
while (!mono_stack.empty() && heights[mono_stack.top()] >= heights[i]) {
mono_stack.pop();
}
right[i] = (mono_stack.empty() ? n : mono_stack.top());
mono_stack.push(i);
}
int ans = 0;
for (int i = 0; i < n; ++i) {
ans = max(ans, (right[i] - left[i] - 1) * heights[i]);
}
return ans;
}
};
思路是遍历i根柱子,找到他左右第一个大于其高度的柱子,就可以计算每个柱子的最大面积
先从左往右遍历,如果单调栈非空并且遍历元素是否小于等于栈顶元素
小于就移除栈顶元素(注意是while)
随后更新当前遍历到的i元素的left【i】(即栈顶),插入i
用同样的方法从右往左遍历,记录左边的
int gettop(int*a,int top)
{
return a[top-1];
}
int largestRectangleArea(int* heights, int heightsSize){
int stack[100001];
int top=0;
int*left=(int*)malloc(sizeof(int)*heightsSize);
int*right=(int*)malloc(sizeof(int)*heightsSize);
memset(left,0,sizeof(left));
memset(right,0,sizeof(left));
for(int i=0;i<heightsSize;i++)
{
while(top!=0&&heights[i]<=heights[gettop(stack,top)])
{
--top;
}
left[i]=top==0?-1:gettop(stack,top);
stack[top++]=i;
}
int stack2[100001];
int top2=0;
for(int i=heightsSize-1;i>=0;--i)
{
while(top2!=0&&heights[i]<=heights[gettop(stack2,top2)])
{
--top2;
}
right[i]=top2==0?heightsSize:gettop(stack2,top2);
stack2[top2++]=i;
}
int ans=0;
for(int i=0;i<heightsSize;++i)
{
int temp=heights[i]*(right[i]-left[i]-1);
ans=ans>temp?ans:temp;
}
return ans;
}
自己写的c语言版的,虽然边界溢出了
和每日温度做对比
单调栈里的元素满足单调递增或递减,都是遍历后与栈顶元素比较,决定要不要移除栈顶元素,并更新数组对应下标的值,然后将遍历元素入栈
适合做往左右第一个大于小于该值的下标
一个月了,记录一下,确实没想到自己能坚持一个月