递归函数创建排列

时间:2017-02-11 00:00:54

标签: scala recursion

我有以下功能,我已经检查了十几次,并且应该完全按照我的意愿工作,但结果却是错误的结果。任何人都可以指出这个功能有什么问题吗?

注意:我打印出递归调用中传递的列表;列表完全按照我的预期。但是,累积结果的称为结果的变量在结尾处不包含正确的排列。此外,我同步访问结果变量,但这没有解决问题;所以,我不认为同步是一个问题。代码可以按原样复制和运行。

import collection.mutable._
def permute(list:List[Int], result:StringBuilder):Unit =
{
    val len = list.size
    if (len  == 0) (result.append("|"))
    else
    {   
        for (i <- 0 until len )
        {
            println("========" + list + "===========")
            result.append( list(i) )
            if (i != len -1) 
            {
                //println("Adding comma since i is: " + i)
                result.append(", ")
            }   
            //println("******** Reslut is:" + result + "***********")
            permute( (sublist(list, i) ), result)               
        }   
    }   

    // This function removes just the ith item, and returns the new list.
    def sublist (list:List[Int], i:Int): List[Int] =
    {
        var sub:ListBuffer[Int] = (list.map(x => x)).to[ListBuffer]
        sub.remove(i)
        return sub.toList
    }
}

var res = new StringBuilder("")
permute(List(1,2,3), res)
println(res)

输出结果为:

========List(1, 2, 3)===========
========List(2, 3)===========
========List(3)===========
========List(2, 3)===========
========List(2)===========
========List(1, 2, 3)===========
========List(1, 3)===========
========List(3)===========
========List(1, 3)===========
========List(1)===========
========List(1, 2, 3)===========
========List(1, 2)===========
========List(2)===========
========List(1, 2)===========
========List(1)===========
**1, 2, 3|32|2, 1, 3|31|31, 2|21|**

2 个答案:

答案 0 :(得分:0)

您的方法存在各种问题,主要问题是您实际上并未实现n元素的排列与n + 1元素的排列之间的递归关系,这是您可以采用n元素的所有排列,并在n + 1元素的每个排列的每个位置插入n元素,以获得n + 1元素的所有排列。< / p>

其中一种方法是Scalatically:

def sortedPermutations(list: List[Int]): List[List[Int]] = list match {
  case Nil | _ :: Nil => List(list)
  case _              => list.indices.flatMap(i => list.splitAt(i) match { 
    case (head, t :: tail) => sortedPermutations(head ::: tail).map(t :: _)
  }).toList
}

println(sortedPermutations(List(1, 2, 3)).map(_.mkString(",")).mkString("|"))

输出:

1,2,3|1,3,2|2,1,3|2,3,1|3,1,2|3,2,1

请注意,这是非常低效的,因为所有列表连接。有效的解决方案是尾递归或迭代。我稍后会为你发帖。

答案 1 :(得分:0)

我认为Dici的解决方案很好,但有点神秘。我认为以下代码更清晰:

def permutations(list: List[Int]): List[List[Int]] = list match
{
    case Nil | _::Nil => List(list)
    case _ =>(  
        for (i <- list.indices.toList) yield
        {
            val (beforeElem, afterElem) = list.splitAt(i)
            val element = afterElem.head
            val subperm = permutations (beforeElem ++ afterElem.tail)
            subperm.map(element:: _)
        }   
    ).flatten
}

val result = permutations(List (1,2,3,4,5) )
println(result.mkString("\n") )

输出将是:

List(1, 2, 3)
List(1, 3, 2)
List(2, 1, 3)
List(2, 3, 1)
List(3, 1, 2)
List(3, 2, 1)