在scala中添加两个由链表表示的数字

时间:2018-09-02 21:11:59

标签: scala singly-linked-list

我是scala的新手,并且想要编写一个代码,按照下面给出的示例在scala中添加两个由链表表示的数字

输入:   第一个列表:5-> 6-> 3 //代表数字365   第二个列表:8-> 4-> 2 //代表数字248 输出量   结果列表:3-> 1-> 6 //表示数字613

我已经在scala中实现了可变单链表的代码,用于向链表添加,更新和插入元素。在下面找到我的代码

    class SinglyLinkedList[A] extends ListADT[A] {
  private class Node(var data: A,var next: Node)
  private var head: Node = null
  def apply(index: Int): A = {
    require(index >= 0)
    var rover = head
    for (i <- 0 until index) rover = rover.next
    rover.data
  }
  def update(index: Int,data: A): Unit = {
    require(index >= 0)
    var rover = head
    for (i <- 0 until index) rover = rover.next
    rover.data = data
  }

  def insert(index: Int,data: A): Unit = {
    require(index >= 0)
    if(index == 0) {
      head = new Node(data, head)
    }
    else{
      var rover = head 
      for (i <- 0 until index-1) 
        rover = rover.next
        rover.next = new Node(data, rover.next)
    }
  }
  def remove(index: Int): A = {
    require(index >= 0)
    if(index == 0){
      val ret = head.data
      head = head.next
      ret
      } else {
   var rover = head 
      for (i <- 0 until index-1) rover = rover.next
        val ret = rover.next.data
        rover.next = rover.next.next
        ret
      }
  }


}

任何人都可以让我知道如何执行链表所表示的两个数字的加法运算。

2 个答案:

答案 0 :(得分:0)

加法如何工作?我的意思是在纸上加上:一个数字在另一个数字之下?

让我们尝试465 + 248

  465
+ 248
  ---

我们从最低有效数字开始:5 +8。但是5 + 8 = 13,因此结果将不适合单个数字。这就是为什么我们就像学前班的老师教给我们的那样:我们留下单位位数,并将十位数带到下一列

   1
  465
+ 248
  ---
    3

现在几十个。 6 + 4 +(带负号)1 =11。同样,我们留下1并携带1到下一列:

  11
  465
+ 248
  ---
   13

最后一列。 4 + 2 + 1 = 7。

  11
  465
+ 248
  ---
  713

结果是713。如果这两个数字中的一个有更多列,或者您要携带最后一个加法,则只需重写其余数字即可。

使用不可变的喜欢列表,它的工作方式相同(稍后我将解释为什么使用不可变的原因):

  1. 同时列出两个列表
  2. 使用两个列表的首部(如果其中一个为空,则由于加法,您可以只返回另一个)
  3. 添加头,并将结果分为进位数字和当前数字(进位为0或0,数字从0到9)
  4. 如果有carry > 0将列表carry :: Nil递归添加到其中一条尾巴上
  5. 在数字前添加递归添加的尾巴

您应该最终得到这样的东西:

val add: (List[Int], List[Int]) => List[Int] = {
  case (a :: as, b :: bs) => 
    val digit = (a + b) % 10
    val carry = (a + b) / 10
    if (carry > 0) digit :: add(add(as, carry :: Nil), bs)
    else digit :: add(as, bs)
  case (as, Nil)   => as
  case (Nil, bs) => bs
} 

add(5 :: 6 :: 4 :: Nil, 8 :: 4 :: 2 :: Nil) // 3 :: 1 :: 7 :: Nil

现在,如果您使用可变列表,它将变得更加棘手。如果要使用可变列表,则要更新其中之一,对吗?哪个-首先?第二?都?您的算法可能会计算出正确的结果,但会屠杀输入。

比方说,您总是将第二个列表添加到第一个列表中,而您想保留第二个列表。如果第二个列表较长,并且您必须为数字添加一些新位置,则必须复制所有剩余的段(否则,您可以例如在第二个列表中更新一个数字并更改第一个)。您还需要携带进位包。

相当违反直觉的行为-数字是不可变的,并且您想表示数字。

答案 1 :(得分:0)

尝试一下:

def add(a: List[Int], b: List[Int], o: Int): List[Int] = (a,b,o) match {
  case (x::xs, y::ys, d) =>
    val v = d + x + y
    (v%10)::add(xs, ys, v/10)
  case (Nil, Nil, 0) => Nil
  case (Nil, Nil, d) => d::Nil
  case (xs, Nil, d) => add(xs, 0::Nil, d)
  case (Nil, ys, d) => add(0::Nil, ys, d)
}