我在Scala中遇到了问题,这是任务声明的摘要:
存在整数列表(长度N,0
输入如下:
4
4 12 8 10
4
4 13 30 100以上示例的输出:
1
2
3
-1
这是我尝试过的: 选择的元素无关紧要。所以我先给出了最大的给定整数列表。然后我选中了第一个检查它是否大于S.如果不是,我也选择了第二个元素,依此类推,直到总和大于或等于S.
这个算法有效,我得到了很多测试用例。但是我有些人超时限制。如果你能指出我如何更快地做到这一点,或者如果有更好的方法来做到这一点,我们将非常感激。
我的代码(Scala):
object Solution {
def main(args: Array[String]) {
val n = readInt()
val arr: Array[Long] = readLine().split(" ").map(_.toLong).sortWith(_ > _)
val sums: Array[BigInt] = new Array(n)
sums(0) = arr(0)
for(i <- 1 until n) sums(i) = sums(i-1) + arr(i)
val t = readInt()
for(i <- 1 to t) {
val s:BigInt = BigInt(readLong())
if(sums(n-1) < s)
println(-1)
else {
var i = 0
while(sums(i) < s) i += 1
println(i + 1)
}
}
}
}
答案 0 :(得分:3)
制作一个完整的总和列表是不必要的,使用BigInt
是浪费的 - 一个Long
最多可以容纳9.2e18,并且你被承诺只会出现1e15。 (事实上,我认为1e15被选中,因此即使Double
也可以保持答案而不会损失精确度。)
此外,您可以对基元使用快速排序,而不是像_ > _
这样的慢速泛型排序,最终会对整数进行装箱。所以:
val arr = {
val in = readLine().split(' ').map(_.toInt)
java.util.Arrays.sort(in)
in
}
然后,使用累加器(Long
将会这样做):
var sum = 0L
并使用while循环搜索答案,请记住最大的元素是最后一个,所以你想从最后开始:
var i = arr.length-1
while (i >= 0 && sum < t) {
sum += arr(i)
i -= 1
}
现在你只需要在用完元素之前检查你是成功还是失败:
val answer = {
if (i < 0) -1
else arr.length - i - 1
}
答案 1 :(得分:0)
这里是(使用O(N)存储器并且使用O(N log N)时间)
scala> import math.{Ordering => Ord}
import math.{Ordering=>Ord}
scala> def search(src: Seq[Long], dst: Seq[Long]): Seq[Int] = {
| val cum = src.sorted(Ord.Long.reverse).scanLeft(0L)(_ + _)
| dst.map{ v => cum.indexWhere(x => x >= v) }
| }
search: (src: Seq[Long], dst: Seq[Long])Seq[Int]
scala> search(Seq(4, 12, 8, 10), Seq(4, 13, 30, 100))
res6: Seq[Int] = List(1, 2, 3, -1)