编程之美读书笔记-队列中取最大值操作问题

原创 2016年08月30日 21:28:07
题目:
假设有这样一个拥有3个操作的队列:
1. EnQueue(v):将v加入队列中
2. DeQueue():使队列中的队首元素删除并返回此元素
3. MaxElement:返回队列中的最大元素
设计一种数据结构和算法,让MaxElement操作的时间复杂度尽可能地低。
解析:设队列长度为N。利用一个数组或链表来存储队列元素,MaxElement时间复杂度为O(N);利用最大堆来存储队列元素,MaxElement时间复杂度为O(1),EnQueue和DeQueue时间复杂度为O(log2N)。按照最大堆的思路,寻找一种新的保存队列中元素相对大小关系的指针集合,并且使得更新这个指针集合的时间复杂度更低。由于栈是一个和队列及其相似的数据结构,我们不妨先看看栈。对于栈来讲,Push和Pop操作都是在栈顶完成的,所以很容易维护栈中的最大值,它的时间复杂度为O(1)。
#include<iostream>  
using namespace std; 
#define MAXN 1000

class MyStack
{
private:
	int stackTop;
	int maxStackItemIndex;
	//最大元素的位置
	int stackItem[MAXN];
	int link2NextMaxItem[MAXN];
	//link2NextMaxItem[i]表示仅小于i位置元素的元素所在位置
	//如果i位置的元素不是当前栈中最大的,这个值就为-1
public:  
	MyStack()
	{
		stackTop = -1;
		maxStackItemIndex = -1;
	}
	bool isEmpty()
	{
		return stackTop == -1;
	}
	bool isFull()
	{
		return stackTop == MAXN - 1;
	}
	void push(int x) 
	{
		if (this->isFull())
		{
			cout << "the stack is full now." << endl;
			return;
		}
		else
		{
			stackItem[++stackTop] = x; 
			if (x > Max()) 
			{
				link2NextMaxItem[stackTop] = maxStackItemIndex;
				maxStackItemIndex = stackTop;
			}
			else
				link2NextMaxItem[stackTop] = -1;
		}
	}
	int pop() 
	{
		int ret;
		if (this->isEmpty())
		{
			cout << "the stack is empty now." << endl;
			return INT_MIN;
		}
		else 
		{
			ret = stackItem[stackTop];  
			if (stackTop == maxStackItemIndex)
			{
				maxStackItemIndex = link2NextMaxItem[stackTop];
			}
			stackTop--;
		}
		return ret;
	}
	int Max() 
	{
		if (maxStackItemIndex >= 0) return stackItem[maxStackItemIndex];
		else return INT_MIN;
	}
};

int main() 
{
	MyStack mystack;
	mystack.push(3);
	mystack.push(4);
	mystack.push(8);
	mystack.push(1);
	mystack.pop();
	mystack.push(7);
	cout << mystack.Max() << endl;
	return 0;
}

如果能够用栈有效地实现队列,而栈的Max操作又很容易实现,那么队列的Max操作也就能有效地完成了。考虑用两个栈来实现一个队列,设为栈A和栈B。
#include<iostream>  
using namespace std; 
#define MAXN 1000

class MyStack
{
private:
	int stackTop;
	int maxStackItemIndex;
	//最大元素的位置
	int stackItem[MAXN];
	int link2NextMaxItem[MAXN];
	//link2NextMaxItem[i]表示仅小于i位置元素的元素所在位置
	//如果i位置的元素不是当前栈中最大的,这个值就为-1
public:  
	MyStack()
	{
		stackTop = -1;
		maxStackItemIndex = -1;
	}
	bool isEmpty()
	{
		return stackTop == -1;
	}
	bool isFull()
	{
		return stackTop == MAXN - 1;
	}
	void push(int x) 
	{
		if (this->isFull())
		{
			cout << "the stack is full now." << endl;
			return;
		}
		else
		{
			stackItem[++stackTop] = x; 
			if (x > Max()) 
			{
				link2NextMaxItem[stackTop] = maxStackItemIndex;
				maxStackItemIndex = stackTop;
			}
			else
				link2NextMaxItem[stackTop] = -1;
		}
	}
	int pop() 
	{
		int ret;
		if (this->isEmpty())
		{
			cout << "the stack is empty now." << endl;
			return INT_MIN;
		}
		else 
		{
			ret = stackItem[stackTop];  
			if (stackTop == maxStackItemIndex)
			{
				maxStackItemIndex = link2NextMaxItem[stackTop];
			}
			stackTop--;
		}
		return ret;
	}
	int Max() 
	{
		if (maxStackItemIndex >= 0) return stackItem[maxStackItemIndex];
		else return INT_MIN;
	}
};

class MyQueue
{
private:
	MyStack mystackA,mystackB;
public:
	int MaxValue(int x, int y)
	{
		if (x > y) return x;
		else return y;
	}
	int Max()
	{
		return MaxValue(mystackA.Max(), mystackB.Max());
	}
	void EnQueue(int v)
	{
		mystackB.push(v);
	}
	int DeQueue()
	{
		if (mystackA.isEmpty())
		{
			while (!mystackB.isEmpty()) mystackA.push(mystackB.pop());
		}
		return mystackA.pop();
	}
};

int main() 
{
	MyQueue myqueue;
	myqueue.EnQueue(8);
	myqueue.EnQueue(3);
	myqueue.EnQueue(4);
	myqueue.EnQueue(1);
	myqueue.DeQueue();
	myqueue.EnQueue(7);
	cout << myqueue.Max() << endl;
	return 0;
}
上述代码能够用栈来实现一个队列。出队的时候,如果A堆栈为空,那么把B堆栈的数据弹出并压入A堆栈这个操作不是O(1)的,虽然如此,但从每个元素的角度来看,它被移动的次数最多可能有3次。所以这种方法的平均时间复杂度是线性的。

版权声明:

相关文章推荐

[编程之美] PSet3.7 队列中取最大值操作问题

问题描述:        假设有这样一个拥有3个操作的队列:       1. EnQueue(v): 将v加入队列中      2. DeQueue(): 使队列中的队首元素删除并返回此元...

编程之美-队列中取最大值操作问题

这是一个要在队列中记录最大值的问题,但每次进队或出队又不能通过遍历去检测最大值的变化。用两个堆栈去实现一个队列是比较常见的方法,书中巧妙的用到了此方法,这样问题就转化为堆栈中取最大值操作问题。由于堆栈...

编程之美:第三章 结构之法 3.7队列中取最大值操作问题

/* 队列中取最大值操作问题: 假设有这样一个拥有3个操作的队列 1EnQueue(v):将v加入到队列中 2DeQueue():使队列中的队首元素删除并返回此元素 3MaxElement:返回队列中...

编程之美-队列中取最大值操作问题

【试题描述】 方法一:时间复杂度O(N) 方法二: 方法三: 这样队列的类定义如下:

编程之美--3.7 队列中取最大值操作问题

思考1 1 利用堆的原理来解决问题

【编程之美】读书笔记:求数组的子数组之和的最大值

问题:一个有N个整数元素的一维数组(A[0],A[1],A[2],...A[n-1]),这个数组中子数组之和的最大值是多少? 该子数组是连续的。例如 数组:[1,-2,3,5,-3,2]返回8;...

【编程之美】读书笔记:寻找数组中的最大值和最小值

问题:对于一个由N个整数组成的数组,需要比较多少次才能把最大值和最小值的数找出来呢?                 解法一:将寻找数组中的最大值和最小值看成是两个独立的问题。分别求出最大值和...

编程之美读书笔记2.15 - 子数组之和的最大值(二维)

问题: 求二维数组(矩阵)的子矩阵之和的最大值。 解法: //********************************************************************...

编程之美之队列中取最大值操作

编程之美之队列中取最大值操作 剑指offer之取栈中最小值操作

队列中取最大值操作问题

题目:        假设有这样一个拥有三个操作的队列:        1.EnQueue(v):将v加入队列中        2.DeQueue:使队列中的队首元素删除并返回...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)