画解数据结构之队列之单调队列

最值问题

第一题

队列模板

struct Queue {
    int data[10001];
    int head, tail;
};
int QueueGetrear(struct Queue*que)
{
    return que->data[que->tail];
}
void QueueClear(struct Queue* que) {
    que->head = que->tail = 0;
}
void QueueEnqueue(struct Queue *que, int dt) {
    que->data[ que->tail++ ] = dt;
}
void QueueDequeueFront(struct Queue* que) {
    ++que->head;
}

int QueueGetFront(struct Queue* que) {
    return que->data[ que->head ];
}
int QueueGetSize(struct Queue* que) {
    return que->tail - que->head;
}
int QueueIsEmpty(struct Queue* que) {
    return !QueueGetSize(que);
}
void QueueDequeueRear(struct Queue*que)
{
--que->tail;
}

typedef struct {
struct Queue q1;
struct Queue q2;//存最大值
int idx;
} MaxQueue;


MaxQueue* maxQueueCreate() {
MaxQueue* ret=(MaxQueue*)malloc(sizeof(MaxQueue));
QueueClear(&ret->q1);
QueueClear(&ret->q2);
ret->idx=0;
return ret;
}

int maxQueueMax_value(MaxQueue* obj) {
if(QueueIsEmpty(&obj->q1))
{
    return -1;
}
else{
    return QueueGetrear(&obj->q2);
}
return 0;
}

void maxQueuePush_back(MaxQueue* obj, int value) {
QueueEnqueue(&obj->q1,value);
if(QueueIsEmpty(&obj->q2))
{
    QueueEnqueue(&obj->q2,value);
}
else
{
    if(QueueGetrear(&obj->q2)<=value)
    {
        QueueEnqueue(&obj->q2,value);
    }
}
}

int maxQueuePop_front(MaxQueue* obj) {
    if(QueueIsEmpty(&obj->q1))
    {
        return -1;
    }
    if(QueueGetFront(&obj->q1)==QueueGetFront(&obj->q2))
    {
        QueueDequeue(&obj->q2);
    }
    int temp=QueueGetFront(&obj->q1);
QueueDequeue(&obj->q1);
return temp;
}

void maxQueueFree(MaxQueue* obj) {
free(obj);
}

我的溢出了

typedef struct {
    struct Queue normal;
    struct Queue max;
    int idx;
} MaxQueue;


MaxQueue* maxQueueCreate() {
    MaxQueue *que = (MaxQueue *)malloc(sizeof(MaxQueue));
    QueueClear( &que->normal );
    QueueClear( &que->max );
    que->idx = 0;
    return que;
}

int maxQueueMax_value(MaxQueue* obj) {                // (1)
    struct Queue *normal = &obj->normal;
    struct Queue *max = &obj->max;
    if( QueueIsEmpty(normal) ) {
        return -1;
    }
    return QueueGetFront(max).value;
}

void maxQueuePush_back(MaxQueue* obj, int value) {     // (2)
    struct Queue *normal = &obj->normal;
    struct Queue *max = &obj->max;
    DataType dt;
    dt.index = ++obj->idx;
    dt.value = value;
    QueueEnqueue( normal, dt );
    while( !QueueIsEmpty(max) && QueueGetRear(max).value <= value ) {
        QueueDequeueRear(max);
    }
    QueueEnqueue(max, dt);
}

int maxQueuePop_front(MaxQueue* obj) {                  // (3)
    struct Queue *normal = &obj->normal;
    struct Queue *max = &obj->max;
    DataType pop;
    if( QueueIsEmpty(normal) ) {
        return -1;
    }
    pop = QueueGetFront(normal);
    QueueDequeueFront(normal);
    while( !QueueIsEmpty(max) && QueueGetFront(max).index <= pop.index)
        QueueDequeueFront(max);
    return pop.value;
}

void maxQueueFree(MaxQueue* obj) {
    free(obj);
}

(1) 如果主队列为空,返回 -1;否则返回辅助队列的队列头元素;
( 2 ) (2)(2) 主队列直接执行插入尾部;辅助队列始终和尾部的元素进行比较,如果小于等于插入值,则一直弹出尾部的元素,再执行插入;
( 3 ) (3)(3) 主队列直接执行出队,并且记录值;辅助队列不断进行判断,辅助下标index <= 主队列index 的全部做出队处理;
单调队列 是一个 双端队列,特点是 头部只做删除,尾部可以做插入和删除。
通用模板

struct Data {
    int value;
    int index;                                      // (1) 
};
#define DataType struct Data
#define maxn 100005

struct Queue {
    DataType data[maxn];
    int head, tail;
};

void QueueClear(struct Queue* que) {
    que->head = que->tail = 0;
}
void QueueEnqueue(struct Queue *que, DataType dt) {
    que->data[ que->tail++ ] = dt;
}
void QueueDequeueFront(struct Queue* que) {
    ++que->head;
}
void QueueDequeueRear(struct Queue*que){
    --que->tail;
}

DataType QueueGetFront(struct Queue* que) {
    return que->data[ que->head ];
}
DataType QueueGetRear(struct Queue*que){
    return que->data[que->tail-1];
}
int QueueGetSize(struct Queue* que) {
    return que->tail - que->head;
}
int QueueIsEmpty(struct Queue* que) {
    return !QueueGetSize(que);
}

第二题

 

int* maxSlidingWindow(int* nums, int numsSize, int k, int* returnSize){
struct Queue*queue=(struct Queue*)malloc(sizeof(struct Queue));//简单地写创建一个队列
int*ret=(int*)malloc(sizeof(int)*numsSize);
*returnSize=numsSize-k+1;
if(numsSize==0)
{
    return NULL;
}
for(int i=0;i<numsSize;i++)
{
    while(!QueueIsEmpty(queue)&&i-QueueGetFront(queue)>k-1)
    {
        QueueDequeueFront(queue);//删除窗口左边的数值
    }//可以直接写queue
    while(!QueueIsEmpty(queue)&&nums[i]>=nums[QueueGetRear(queue)])
    {
        QueueDequeueRear(queue);
    }//形成单调递减序列
    QueueEnqueue(queue,i);
    if(i>=k-1)
    {
        ret[i-k+1]=nums[QueueGetFront(queue)];
    }
}
return ret;
}

用辅助队列的时候只需要struct Queue

1.遍历每个下标的时候删除窗口左侧的下标,并且拆除比当前小的尾部,形成单调递减序列

2.每个滑动窗口代表中当前

线性DP--动态规划

第一题

1.动态规划

 dp[i]是以第i个元素结尾的最大得分,
所以每次只要找i-1到i-k的dp[j]的最大值,边界条件dp[0]=nums[0]

int maxResult(int* nums, int numsSize, int k){
int dp[numsSize];
dp[0]=nums[0];//dp[i]是以第i个元素结尾的最大得分,
//所以每次只要找i-1到i-k的dp[j]的最大值
for(int i=1;i<numsSize;i++)
{
    for(int j=max(0,i-k);j<i;j++)
    {
        maxdp=max(maxdp,dp[j]);
    }
    dp[i]=nums[0]+maxdp;
}
return dp[numsSize-1];
}

用滑动窗口做的没看懂。。 

while(!QueueIsEmpty(q) && i - QueueGetFront(q) > k)          // (4) 
            QueueDequeueFront(q);

表示以i开始,k+1为长度的话的滑动窗口queue

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值