【问题标题】:How to rotate an array using array reversal technique?如何使用数组反转技术旋转数组?
【发布时间】:2021-07-23 16:37:04
【问题描述】:

我正在尝试使用数组反转方法从特定位置旋转数组。

输入数组:[1,2,3,4,5,6,7] d = 3 输出数组:[5,6,7,1,2,3,4]

为了实现这一点,我想分三个步骤处理数组。 Step1:从起始位置反转数组,直到 d => [4,3,2,1,5,6,7] Step2:将数组从d反转到数组末尾=> [4,3,2,1,7,6,5] Step3:从 Step2 反转完整数组 => [5,6,7,1,2,3,4]

我没有遵循任何函数式编程模式,因为我想逐步检查算法。

  val arr = Array[Int](1, 2, 3, 4, 5, 6, 7)
  def reverseAlgo(brr: Array[Int], start: Int, end: Int): Unit = {
    var temp = 0
    for(i <- start until end/2) {
      temp = brr(i)
      brr(i) = brr(end-i-1)
      brr(end-i-1) = temp
    }
    brr.foreach(println)
  }

Step1 工作正常:

  reverseAlgo(arr, 0, 3)

输出:

3
2
1
4
5
6
7

但是 Step2 没有产生所需的输出:

  reverseAlgo(arr, 3, 7)

输出:

3
2
1
4
5
6
7

如你所见,数组的输出应该是:3,2,1,7,6,5,4 由于Step2的输出不正确,所以最终的输出也是错误的。

第三步:

reverseAlgo(arr, 0, arr.length)

输出:

7
6
5
4
1
2
3

谁能告诉我我在这里做错了什么?

【问题讨论】:

    标签: arrays scala


    【解决方案1】:

    为什么不做这么简单的事情呢?

    import scala.collection.immutable.ArraySeq
    import scala.reflect.ClassTag
    
    def rotate[T : ClassTag](arr: ArraySeq[T])(pos: Int): ArraySeq[T] = {
      val length = arr.length
      ArraySeq.tabulate[T](n = length) { i =>
        arr((i + 1 + pos) % length)
      }
    }
    

    可以这样使用:

    rotate(arr = ArraySeq(1, 2, 3, 4, 5, 6, 7))(pos = 3)
    // res: ArraySeq[Int] = ArraySeq(, 5, 6, 7, 1, 2, 3, 4)
    

    可以看到运行here的代码

    【讨论】:

      【解决方案2】:

      您的代码仅在范围从零开始时才有效。

      for(i <- start until end/2) {
        temp = brr(i)
        brr(i) = brr(end-i-1)
        brr(end-i-1) = temp
      }
      

      应该是这样的:

      for(i <- 0 until (end-start)/2) {
        temp = brr(start+i)
        brr(start+i) = brr(end-i-1)
        brr(end-i-1) = temp
      }
      

      通过此更改,您的代码可以正常工作。

      【讨论】:

        【解决方案3】:

        要避免变异,但如果必须,递归仍然有用。

        def reversePart[A](arr: Array[A], start: Int, end: Int): Unit = {
          def loop(a:Int, b:Int): Unit =
            if (a < b) {
              val temp = arr(a)
              arr(a) = arr(b)
              arr(b) = temp
              loop(a+1, b-1)
            }
          loop(start max 0, end min arr.length-1)
        }
        
        val test = Array(1, 2, 3, 4, 5, 6, 7)
        reversePart(test, 0, 3)   //Array(4, 3, 2, 1, 5, 6, 7)
        reversePart(test, 4, 7)   //Array(4, 3, 2, 1, 7, 6, 5)
        reversePart(test, -1, 99) //Array(5, 6, 7, 1, 2, 3, 4)
        

        【讨论】:

          【解决方案4】:

          我知道这并不能直接回答您的问题,但作为参考和对稍微不同的方法感兴趣的读者,一种可能性是将其作为视图来实现。

          在此示例中,Rotate 实现了逻辑,而IndexedSeqViewRotaterotate 方法添加为任何 IndexedSeqView 的扩展,只要它在范围内。

          在测试中,我将视图具体化为Vectors 以利用相等性,当然您也可以将它们具体化为Array

          import scala.collection.IndexedSeqView
          import scala.collection.IndexedSeqView.SomeIndexedSeqOps
          
          final class Rotate[A](underlying: SomeIndexedSeqOps[A], n: Int) extends IndexedSeqView[A] {
            @inline private def rotateIndex(i: Int): Int = ((i - n) % length + length) % length
            override def apply(i: Int): A = underlying(rotateIndex(i))
            override lazy val length: Int = underlying.length
          }
          
          final implicit class IndexedSeqViewRotate[A](val underlying: IndexedSeqView[A]) extends AnyVal {
            def rotate(n: Int): IndexedSeqView[A] = new Rotate(underlying, n)
          }
          
          assert(Array().view.rotate(7).to(Vector) == Vector.empty)
          assert(Array(1,2,3,4,5,6,7).view.rotate(7).to(Vector) == Vector(1,2,3,4,5,6,7))
          assert(Array(1,2,3,4,5,6,7).view.rotate(0).to(Vector) == Vector(1,2,3,4,5,6,7))
          assert(Array(1,2,3,4,5,6,7).view.rotate(1).to(Vector) == Vector(7,1,2,3,4,5,6))
          assert(Array(1,2,3,4,5,6,7).view.rotate(3).to(Vector) == Vector(5,6,7,1,2,3,4))
          assert(Array(1,2,3,4,5,6,7).view.rotate(-1).to(Vector) == Vector(2,3,4,5,6,7,1))
          

          您可以使用此代码here on Scastie

          【讨论】:

            猜你喜欢
            • 2018-07-06
            • 2015-09-19
            • 2019-12-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-07-18
            • 2023-01-12
            • 1970-01-01
            相关资源
            最近更新 更多