我接受了这个采访:
如果N [i]>,则称数字是“反向排序的”。 N [j]对于i<学家 例如,在列表中:3 4 1 6 7 3,反向排序的项目是(3,1)(4,1)(4,3)(6,3)(7,3)。
如何在O(nlogn)时间内获得反向排序项目对的数量。
答案 0 :(得分:18)
可以使用合并排序的修改版本在O(n log n)时间内执行此操作。除法正常,但您可以在合并时计算反转。每次从左侧列表中的项目中选择右侧列表中的项目时,会按左侧列表中剩余项目的数量递增反转计数。因此,在每个级别,反转次数是合并期间发现的反转次数加上每次递归调用所发现的反转次数。
答案 1 :(得分:4)
请注意,请阅读本答案的底部,了解为什么它实际上可以解决问题。我读错了这个问题。
在一般情况下无法实现。考虑清单:
n,n-1,n-2 ... 4,3,2,1
对将是:
(n,n-1),(n,n-2)...(n,2),(n,1),(n-1,n-2),(n-1,n- 3)......(3,2),(3,1),(2,1)
因此有O(n ^ 2)对,因此列表不能在O(n log n)中构建
但是,您可以通过列表的一次传递来执行此操作:
对于您的示例:
名单:3 4 1 6 7 3
从第二项开始
堆(3) 第(7)项输出(7,3)
堆(3,7) 第(6)项
搜索并找到7,输出(6,3)
堆(3,6,7) 第(1)项
搜索并找不到任何内容
堆(1,3,6,7) 第(4)项搜索并找到3和1.输出(4,3)(4,1)
等...
编辑,实际上可能是
由于JoshD正确地指出我们正在寻找元素的数量,您可以使用B树而不是堆,然后您可以获得小于当前项的元素数量并将其添加到计数器。
答案 2 :(得分:0)
这可以通过创建二叉搜索树来解决,这样每个节点都包含其左子树的大小。
以原始数组的相反顺序将值添加到BST。保留一个总和,每次我们在添加节点时向右移动时,被比较的当前节点的左子树+ 1的大小被添加到最终总和(因为添加的值大于该节点并且其左侧的每个值子树)。
构建树是nlogn,一旦树构建,总和将是对的数量。
根据要求,需要为重复的数字添加特殊处理(即,如果(4,3)显示两次,是否应计算两次)
答案 3 :(得分:0)
从右到左的遍历,红黑树,其中每个节点通过其各自子树的大小进行扩充。因此需要O(logn)来查找给定值之下的元素数量。
答案 4 :(得分:0)
正如@jlewis42指出的那样,您可以使用合并排序的修改版本。我只想添加,您可以使用任何标准comparison sort算法,只要最坏情况下的运行时间是n log n
,通过“检测”它来计算反转,因为它的工作原理。另请参阅dupe附近的this。