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

画解数据结构之队列之单调队列,第1张

最值问题

第一题

队列模板

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) 主队列直接执行插入尾部;辅助队列始终和尾部的元素进行比较,如果小于等于插入值,则一直d出尾部的元素,再执行插入;
( 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;ik-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

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

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

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

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/867450.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-12
下一篇 2022-05-12

发表评论

登录后才能评论

评论列表(0条)