在大型数组中计算较小或相等元素的更快方法?

时间:2019-01-10 07:38:32

标签: arrays algorithm search

我需要减少代码的时间复杂度,到目前为止,我尝试对其进行预排序,并使用二进制搜索来查找所需元素的索引,并使用索引来查找键号之前有多少个元素,但是我可以无法通过,因为我的代码很慢。我还有其他方法可以使此代码更快吗?

重要细节:

  • 我需要在一个大数组和多个查询(数组保持不变)下运行此代码,两者最多为100k。
  • 每个元素的价值最多为10亿美元。
  • 此问题的时限为0,1秒

示例:

假设我有一个包含15个元素的数组,并且要执行5个查询。

数组:1002 19 3 8 22 123 14 5234 123 657 41 829 34 2314 15

查询:100 1000 78 3 1

输出:8 12 8 1 0

我尝试对其进行预排序并使用二进制搜索,但仍然无法通过0,1s的时间限制。

<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.6/fabric.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">
<div class="container">
<div class="row">
<div class="g-container-upper">
	<div id="g-container" >
		<div id="left-canvas" class="row justify-content-md-center">
			<svg id="left-svg">
				<g>
					<line id="svg-left-line" x1="5" x2="5" y1="0"></line>
				</g>
				<g></g>
			</svg>
			<canvas id="g-canvas" style="border:1px solid #000000;"></canvas>
		</div>
    </div>
    <div class="row">
		<div id="bottom-canvas">
			<svg id="bottom-svg" class="row justify-content-md-center">
				<g>
					<line id="svg-bottom-line" x1="0" y1="5" y2="5"></line>
				</g>
			</svg>
		</div>
	</div>
</div>
</div>
</div>

2 个答案:

答案 0 :(得分:1)

通常,您的方法是正确的,应该提供平均时间NlogN + MlogN,其中N是数组大小,M是查询数。

但是qsort的实现还不够好-它总是选择正确的元素作为数据透视表,并且对于某些数组(已排序的数组或包含重复的元素)给出二次排序时间!

如果您不能使用标准库中的排序例程,只需更改实现-在随机索引处获取数据点或使用“ median of three”方法

P.S。还可以考虑用Hoare的方法代替使用过的Lomuto的分区方法(它不是那么简单,但是更快)

答案 1 :(得分:0)

首先,您能告诉我们您为给定的迭代列表固定了100k元素数组时,当前选择的执行时间是多少?这将使我们了解您离极限有多远。

第二,执行时间不仅取决于复杂度,还取决于每个循环的执行时间。这就是为什么您可以拥有两种具有不同复杂度的算法,但是具有较高复杂度的一种算法比另一种算法运行速度更快的原因仅在于它在足够少的元素上运行。 这样说,对于您来说,复杂性肯定是有作用的。但是,每个循环的运行时间很重要,这取决于实现方式。因此,我可以提出以下建议:

  • 提高编译器的优化级别(-O选项)
  • 更改一些代码。例如,mid = left + (right-left)/2;可以简化为mid = (left + right) >> 1;。这将已经提高了代码速度。 (我已经编辑了此部分,将右移更改为1)
  • 更改循环检查。对其进行转换以针对0进行测试,您的代码将更快。
  • 此外,每项测试都会花费您时间,因此最好使用读写来代替测试,以查看您是否必须读写。

注意:

您也许可以尝试另一种方法,即根据每个数字将数字组织成树。例如,12 123 1237 15 24 26 1256将构建一棵树,就像最后一个数字将被标记以表明它是叶子(以数字结尾)一样。当然也可以从二进制值构建该树

1 - 2 - 3 - 7 - 5 - 6 - 5 2 - 4 - 6

此后,只需要沿着树行进并比较每个数字的长度和值即可。

不过只是个主意!