参考自:https://blog.csdn.net/XY20130630/article/details/50635756
题意:一个序列被称为是不无聊的,仅当它的每个连续子序列存在一个独一无二的数字,
即每个子序列里至少存在一个数字只出现一次。
给定一个整数序列,请你判断它是不是不无聊的。
分析:预处理每个元素上一次出现位置和下一个出现位置,
我们发现对于一个子序列[L,R]来说,
如果存在pre[i]
否则就不满足,那么我们分治处理这个问题,
从两边往中间寻找这个i,那么每次拆开的复杂度就是拆成的两个序列中较小的一个,
所以这是一个逆启发式合并的过程,复杂度O(nlogn)
一、在区间[l,r]找到一个只出现一次的元素P(如果不存在,那么序列无聊)
二、递归处理区间[l,p−1]和区间[p+1,r]
关键在于如何找到一个只出现一次的元素。
首先,我们得知道如何判断一个元素是不是只出现一次。
我们可以用STL中的map记录与当前元素值相同的上一个元素(下一个元素)的位置,然后滚动更新即可。
因为map的所有操作都是O(logn)的,所以预处理的时间复杂度为O(nlogn)
所以,我们就可以用O(1)的时间判断出一个元素是不是只出现一次了。
若从左到右扫描整个序列,那么最坏情况,这个元素在序列的最右边,则
T(n)=T(n−1)+O(n)≥T(n2)=O(n2)
根据二分法一般是尽量分成两个数量尽量接近的数列,我们可以考虑从两边往中间找。(这就是启发式)
此时,最坏情况为这个元素在序列的正中间,则
T(n)=2T(n/2)+O(n),解得T(n)=O(nlogn)
所以算法的总时间复杂度为O(nlogn)
#include#include #include #include