google2016面试题-count of smaller numbers after self

这是google2016的面试题,给定一个数组array[],返回一个计数数组count,count[i]表示array[]中第i个元素右边有多少个小于array[i](i>=0)
示例:
输入:array[]=[3,6,2,1]
输出:count[]=[2,2,1,0]

分析思路:
不难想到O(n2)的方法,不断的用for循环来找目标值。难点在于如何在小于O(n2)时间复杂度下找到方法。其实像这种统计个数问题我们完全可以采用线段树的思想来做。先给大家举个简单例子:

一维坐标轴上我这有三条线段区间,分别为[1,5],[2,5],[4,10],请判断点2都在哪几条区间出现过。高时间复杂度的算法就不写了,直接上效果非常好的线段树。

线段树:和正常的树类似,只不过每个节点保存的是一段区间,同时每个节点添加计数变量count,用来记录哪个数值点在该条线段区间出现过。表示建树的过程是首先在根节点保存最大线段区间跨度,然后采用与折半查找类似的方式创建根节点的左右子树。以三条线段[1,5],[2,5],[4,10]为例,其线段树构造如下图,初始conut为全0.
google2016面试题-count of smaller numbers after self_第1张图片

为了判断点2都在哪些区间出现过,我们需要将三条线段在刚刚创建的线段树上。线段[1,5]就要切割成[1,3],[4,5],这样线段树[1,3],[4,5]这两个节点的count值要加1,表示[1,5]这条线段出现过,线段[1,5]和节点[2,3]和[4,5]是等价的。同理,线段[2,5]要切割成[2,3]和[4,5],线段树[2,3]和[4,5]这两个节点count值也要加1。目前为止节点[4,5]的count计数已经变为了2。同样线段[4,10]分割为[4,5]和[6.10],对应count值要加1。这样三条线段就挂在完毕了,只要在线段树中用折半查找的方式找到[2,2]这个节点,记录下经过“挂”的节点的count值,取和就是最终经过的线段数。

明天给啦

你可能感兴趣的:(google2016面试题-count of smaller numbers after self)