前沿:
自强不息:投入,每一个环节细致。
在乎方法;及时沟通
想象力,计算机科学相对比较抽象。
根据算例,跑一些算例。实地去计算、去使用。
栈排序
栈 stack : pop 出栈 、 push 进栈 、 LIFO 后进先出
insertionsort:插入排序 O(I+n)( I(inversion):逆序对 度量序列的有序性 n:序列输入长度 )
输入敏感:算法复杂度与输入长度有关的
假设前面的(prefix)均为有序的(S,sorted),后面的(suffix)为随机的(R,random)
将后面默认无序的部分逐个插入前面的sorted中。
常规用数组向量来实现。
in-place = 就地 (即要求算法所允许使用的空间)
用栈存储输入、输出数据。算法空间复杂度为O(1)。
将S与R各自组为栈。R的栈顶为即将要插入的栈元素。O(1)说明有一个可以放外面(即要插入的元素)。
将S的栈顶元素pop到R中。直至需要插入的区域,将要插入的元素push进S栈。将原有pop出去的栈顶
S栈内始终为有序的元素。
比较S栈顶与待排序元素大小->决定挪动方向。
若 S栈顶元素小,那么待排序元素直接push进入
若 S栈顶元素大,那么比待排序元素大的全部push进R。直至出现前者情况,逐个push进入。
stacksort伪代码(栈R、S)
stack<int> S:输出的载体
int t = R.pop() ;
while ( ! R.empty() )
if( S.empty() || S.top() <= t ) # S栈顶空(思维方式:栈前有一个若有若无的很小的元素) 或者 S栈顶元素比待排序元素小
S.push(t) ; t = R.pop();
else
R.push(S.pop());
S.push(t) #不遗漏最后一个t
return s;
利用python实现栈排序功能的详细代码请见
https://blog.csdn.net/weixin_43829465/article/details/95925876
最大直方图面积
Maximal rectangle in a histogram (可以推广到 matrix。 二者存在一个规约)
matrix 先固定底边的情况->直方图问题
思路最重要、动眼观察比动手重要。
Histogram k为某个极小值点(为上面的封顶点)
ik k jk 任意一个k均有一个左右均挡住的点(左右卡位点)。 注意左右两边默认有最小的取值哨兵。
S = H[K]*(jk - ik -1) ( -1:若jk与ik挨着的时候补上-1就能保证为零)
Bruteforce 暴力 复杂度平方量级
遍历k个极小值点。记录下每个极大值面积。再做比较
divide-conquer 分治(快速排序、归并排序)
以k点作为pivot。k点为极小值点。分这一步完成了。
治:在左边的区间和右边的区间寻找最大的矩形
merge(合并)。左右最大的矩形进行合并。
max Rect(H,lo,hi)
k = find pivot(H,lo,hi)
左边最大矩形面积 max Rect(H,lo,k) 默认左闭右开
右边最大矩形面积 max Rect(H,k+1,hi)
横贯的最大矩形面积 S = H[K]*(jk - ik -1)
取三者的最大值 返回
时间复杂度与空间复杂度
时间复杂度T(n): 最好的话两个问题 分一半 2T(n/2) 或者 最坏情况 T(n-1)
寻找极小值:遍历寻找在lo与hi的最小值 O(n) (2T(n/2)变为 nlogn T(n-1)变为n方)
可以制作一个极小值查询表(预处理) : lookup table 查询表 二维表 横坐标lo 纵坐标hi
构造需要的时间O(n方),需要的存储空间O(n方),查询需要的时间O(1)
对区段进行查询 Min\Max\Sum 可以利用线段树进行查询 segment tree
构造需要的时间O(n或nlogn),需要的存储空间O(n),查询需要的时间O(logn)
因此采用线段树 查询时间为logn 加上最大的时间复杂度T(n-1) 最大的空间复杂度为nlogn
引入栈解决这个问题
栈从底到顶会越来越大,必须是左边第一个比他矮的。
第二种情况,在右边比k点的极小值 还小。
伪代码:
maxRect(H[ ] ,n)
stack(rank) M (暗示栈顶均是min极小值)M栈元素从栈底到栈顶逐渐增大。
int maxRect =0;
for (rank k=0 ; k < n ; ___ )
if (M.empty() || H[M.top()] <= H[k] )
M.push(k++); # 将k push进去
else # 找到了相应的元素 H[M[top]]*( H[ M[top-1] ] , k )
t = M.pop();
maxRect = max( maxRect , H[t] *(M.empty()? k ; (k-M.top()-1)) ) #注意M栈是否为empty 若是 则要单独处理
while( ! M.empty() )
t = M.pop()
小结: 用栈求解最大直方图面积 空间复杂度O(n)
复杂度主要在pushpop操作上,每个元素最多进栈一次,是一个线性的算法。