如何有效地去除Scala中的var

如何有效地去除Scala中的var,scala,functional-programming,priority-queue,var,Scala,Functional Programming,Priority Queue,Var,我正在努力解决这个问题 解决方案 def minCost(arr: Array[Int]):Int = { val minHeap = scala.collection.mutable.PriorityQueue.empty[Int].reverse arr.foreach{ ele => minHeap += ele } var sum =0 while(minHeap.size >1){ val fir

我正在努力解决这个问题

解决方案

def minCost(arr: Array[Int]):Int = {

  val minHeap = scala.collection.mutable.PriorityQueue.empty[Int].reverse
    
  arr.foreach{ ele =>
    minHeap += ele
  }
    
  var sum =0
    
  while(minHeap.size >1){
    
    val first = minHeap.dequeue()
    val second = minHeap.dequeue()
    
    val length = second + first//3+3 =6+9
    sum = sum + (first +second)//3+6+9
    
    minHeap.enqueue(length)
  }
    
  sum
}
我想摆脱
while
循环和
var
。有人能提出更好的解决方案吗

在下面试用

val res =minHeap.foldLeft(0){
  (x,y)=>
    val sum =x+y
    minHeap.enqueue(sum)
    sum
}

println(res)
res

如果您只想删除
var
while
,但仍然使用可变的PriorityQueue(诚实地说这是一个很好的折衷方法,可能是在实际代码中最好的方法),那么您可以使用尾部递归方法

type Ropes=List[Int]
def connectRopes(ropes:ropes):Int={
val queue=PriorityQueue.from(ropes).反向
@注释.tailrec
def循环(剩余:Int,acc:Int):Int={
如果(剩余==0)acc
如果(剩余==1)acc
否则{
val rope1=queue.dequeue()
val rope2=队列。退出队列()
val newRope=绳索1+绳索2
queue.addOne(newRope)
环(剩余-1,acc+新绳)
}
}
循环(剩余=queue.size,acc=0)
}
但是,如果您想编写一个完全不可变的解决方案来适应不可变的数据结构,您可以这样做:

def connectRopesFullImmutable(ropes:ropes):Int={
@注释.tailrec
def回路(剩余:绳索,附件:Int):Int=
剩余比赛{
案例无=>
行政协调会
案例:无=>
行政协调会
案例1::rope2::Nil=>
缆绳1+2+acc
案例1::案例2::案例尾=>
@注释.tailrec
def findTwoMin(剩余:Ropes,min1:Int,min2:Int,acc:Ropes):(Int,Int,Ropes)=
剩余比赛{
箱绳::尾=>
如果(rope
(最小1,最小2,acc)
}
val(最小1,最小2,绳索)=
如果(rope1

回答注释问题的空间复杂度是(AFAIK)O(1),因为算法是尾部递归函数,我们不使用堆栈,我们只操作相同的列表,所以也不使用堆。
时间复杂度是O(N^2),因为我们在外循环中有一个内环,这意味着该算法效率非常低

我们可以尝试通过保持剩余绳索的列表始终保持排序来对其进行一些优化;如下图所示。它应该使用O(N log(N)),但仅仅因为不使用可变优先级队列,仍然需要大量的样板文件和低效率

def connectRopesFullImmutableOptimized(ropes:ropes):Int={
@注释.tailrec
def回路(剩余:绳索,附件:Int):Int=
剩余比赛{
案例1::案例2::案例尾=>
val newRope=绳索1+绳索2
@注释.tailrec
def insertSorted(剩余:绳索,附件:绳索):绳索=
剩余比赛{
箱子绳索::绳索=>
如果(新绳>绳)插入排序(剩余=绳,绳::acc)
else acc reverse_u216;::(新绳::绳::绳)
案例无=>
(新绳::acc)。反向
}
循环(剩余=插入排序(剩余=尾部,acc=列表.空),acc+新绳)
案例=>
行政协调会
}
回路(剩余=已分拣的绳索,acc=0)
}


您可以看到正在运行的代码。

如果您只想删除
var
while
,但仍然使用可变的优先级队列(诚实地说这是一个很好的折衷方法,可能是在实际代码中最好的方法),您可以使用尾部递归方法

type Ropes=List[Int]
def connectRopes(ropes:ropes):Int={
val queue=PriorityQueue.from(ropes).反向
@注释.tailrec
def循环(剩余:Int,acc:Int):Int={
如果(剩余==0)acc
如果(剩余==1)acc
否则{
val rope1=queue.dequeue()
val rope2=队列。退出队列()
val newRope=绳索1+绳索2
queue.addOne(newRope)
环(剩余-1,acc+新绳)
}
}
循环(剩余=queue.size,acc=0)
}
但是,如果您想编写一个完全不可变的解决方案来适应不可变的数据结构,您可以这样做:

def connectRopesFullImmutable(ropes:ropes):Int={
@注释.tailrec
def回路(剩余:绳索,附件:Int):Int=
剩余比赛{
案例无=>
行政协调会
案例:无=>
行政协调会
案例1::rope2::Nil=>
缆绳1+2+acc
案例1::案例2::案例尾=>
@注释.tailrec
def findTwoMin(剩余:Ropes,min1:Int,min2:Int,acc:Ropes):(Int,Int,Ropes)=
剩余比赛{
箱绳::尾=>
如果(rope
(最小1,最小2,acc)
}
val(最小1,最小2,绳索)=
如果(rope1import scala.collection.mutable.PriorityQueue

def minCost(arr: Array[Int]): Int =
  List.unfold(PriorityQueue(arr:_*).reverse){ pq =>
    Option.when(pq.size > 1) {
      val link = pq.dequeue() + pq.dequeue()
      pq.enqueue(link)
      (link, pq)
    }
  }.sum