【一周编程学习】--3.队列与堆的学习-LeetCode第239题

 

1.队列与堆学习笔记


  • 队列的存储结构:

是一种先进先出的线性表,只允许在一端插入数据(队尾),在另一端进行删除操作(队头)

  • 头指针 front 和 尾指针 rear

Front(队头):从队列中获得最前面的元素。

Rear(队尾):从队列中获得最后面的元素。

  • 队列的操作

Enqueue(入队/插入):添加元素到队列中。如果队列满了,则表示溢出(Overflow)情况。

Dequeue(出队/删除):从队列中剔除元素。该元素被压出(pop)的顺序与push(压入)的顺序一样。如果队列是空的,则表示下溢(underflow)情况。

队列初始条件:队头指针=队尾指针=0

队列满条件:队尾指针=m(设队列当前容量为m)

队列空条件:队头指针=队尾指针


利用完全二叉树的结构来实现的一种数据结构,时间复杂度在O(1)~O(logn),堆的落地实现是数组

完全二叉树不清楚的小伙伴请看这篇文章:https://www.cnblogs.com/myjavascript/articles/4092746.html

堆中某个节点的值总是不大于或者不小于其父节点的值,将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。

注意:堆内的元素并不一定数组下标顺序来排序的!

请看堆排序的代码:(这是以前学堆时写的)

//堆排序(大根堆)
void HeapInsert(int *A,int len)
{
	if(A==NULL*&&len<2)
	{
		return;
	}
	for(int i=0;i<len;i++)
	{
		heapInsert(A,i);
	}
	int heapSize=len;
	swap(A,0,--heapSize);
	while(heapSize>0)
	{
		heapify(A,0,heapSize);
		swap(A,0,--heapSize);
	}
}
void heapInsert(int *A,int index)
{
	while(A[index]>A[(index-1)/2])
	{
		swap(A,index,(index-1)/2);
		index=(index-1)/2;
	}
}

void heapify(int *A,int index,int heapSize)
{
	int left=index*2+1;
	while(left<heapSize){
		int largest=left+1<heapSize&&A[left+1]>A[left]?left+1:left;
		largest=A[index]>A[largest]?index:largest;
		if(index==largest)
			break;
		swap(A,index,largest);
		index=largest;
		left=index*2+1;
	}
}
  • 参考:

 1.https://www.cnblogs.com/JVxie/p/4859889.html

2.https://www.cnblogs.com/helloworld-c/p/4854463.html    密码:abcd111


2.总结:

这两天学习了哈希思想与链表的操作,虽然题难度一般,但使用的知识点挺多的,可见训练营的组织者相当用心。我使用了map和set做了第一天的题;使用快慢指针和map做了第二天的题;虽然自己的编程水平目前很一般,但在逐渐养成习惯。

 


3.LeetCode第239题

题意是:给出一个可能包含重复的整数数组,和一个大小为 k 的滑动窗口, 从左到右在数组中滑动这个窗口,找到数组中每个窗口内的最大值。

最开始想的是从开始位置i,逐个遍历;j=i;i=i+k;找到最大值,两层循环,发现这样时间复杂度有些大;

于是绞尽脑汁想,想用队列来做,无奈没做出来,参考了这个人的方法,用的是双端队列。

借助一个辅助队列(双端队列),从头遍历数组,根据如下规则进行入队列或出队列操作: 

  1. 1. 如果队列为空,则当前数字入队列 
  2. 2. 如果当前数字大于队列尾,则删除队列尾,直到当前数字小于等于队列尾,或者队列空,然后当前数字入队列 
  3. 3. 如果当前数字小于队列尾,则当前数字入队列 
  4. 4. 如果队列头超出滑动窗口范围,则删除队列头 

这样能始终保证队列头为当前的最大值


使用C++编程实现:

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
	vector<int> res;
	int n=nums.size();
	if(n==0||k>n)
		return res;
	deque<int> myQueue;
	for(int i=0;i<n;i++)
	{
		if(!myQueue.empty())
		{
			if(i>=myQueue.front()+k)
				myQueue.pop_front();
			while(!myQueue.empty()&&nums[i]>=nums[myQueue.back()])
				myQueue.pop_back();
		}
		myQueue.push_back(i);
		if(i+1>=k)
			res.push_back(nums[myQueue.front()]);
	}
	return res;
    }
};

参考:

1.https://www.jianshu.com/p/7662caf4f39c

猜你喜欢

转载自blog.csdn.net/wxq_1993/article/details/85854695