【问题标题】:Counting the number of moves for sorting an array if only unit shift are allowed如果只允许单位移位,则计算对数组进行排序的移动次数
【发布时间】:2015-06-01 08:53:45
【问题描述】:

所以,我有一个包含整数的数组。我需要对其进行排序。但是,我唯一可以执行的操作是单位移位。也就是说,我可以将序列的最后一个元素移到它的开头。

          `a1, a2, ..., an → an, a1, a2, ..., an - 1.`

我需要对序列进行排序的最少操作数是多少?

数组中的整数个数最多为 10^5。每个整数单独值也可以是 10^5。此外,如果数组已经排序,则打印 0,否则如果数组无法按单位移位排序,则打印 -1。

我想到的解决方案:

  1. 检查数组是否已排序。
  2. 如果数组已排序,则打印 0 否则
  3. 设置计数 = 0
  4. 将数组旋转一个单位并增加计数。
  5. 检查数组是否排序:如果是,打印计数和中断,否则
  6. 重复步骤 4-5 直到 count

现在,上述解决方案的时间复杂度为 O(n^2)。因为,如果数组已排序,我正在检查每个单独的元素,并且此检查需要 O(n) 时间,并且我有 n 个元素,因此它是 O(n^2)。

谁能给我建议其他更好的方法? 谢谢!

PS:我非常努力地想了一些其他的方法。我达到了计数反转,但这并没有真正帮助。

【问题讨论】:

  • 所以这个“排序”例程可以排序的唯一输入是可能已经旋转了一定量的排序数组,而您要做的就是撤消旋转?

标签: arrays algorithm sorting


【解决方案1】:

只需迭代数组,找到第一个索引i,使得arr[i] > arr[i+1](如果没有这样的索引,我们就完成了,因为数组已经排序了),然后检查arr[i+1],...,arr[n]是否排序,如果@ 987654324@。如果是,可以通过 n-i 旋转来完成。

否则,没有办法。

时间复杂度为 O(n),空间复杂度为 O(1)。


附录:算法的正确性:

权利要求 1:

如果数组不能拆分成两个数组 arr[1],arr[2],..,arr[i]arr[i+1],...,arr[n] - 均已排序, 那就没有办法了。

证明:
让我们假设iarr[i] > arr[i+1] 所在的第一个索引,并让j 是其他一些索引,例如arr[j] > arr[j+1], j!=i。一定有这样的,因为arr[i+1],...,arr[n] 是未排序的。

根据定义,虽然j+1 不是“单位移位”,但数组是未排序的。
刚移位后,由于arr[i] > arr[i+1]仍然没有排序,又一次移位后,arr[j]又在arr[j+1]之前,违反了排序顺序。
因此,数组无法排序。

权利要求 2:

假设一个数组可以拆分为两个有序数组 arr[1],...,arr[i]arr[i+1],...,arr[n]
还假设 arr[i] > arr[i+1]
然后,数组可以“单位移位”成 排序一,当且仅当arr[n] <= arr[1]

证明:

<---
数组未排序,因此至少要进行一次单位移位。这个单位移位将arr[n]放在arr[1]之前,除非arr[n]<=arr[1],否则数组永远不会被排序

--->
假设arr[n]<=arr[1],那么通过移动arr[i+1],...,arr[n],我们得到以下数组:

arr[i+1],arr[i+2],...,arr[n],arr[1],arr[2],...,arr[i]

请注意arr[i+1]<= arr[i+2] <= .... <= arr[n],因为我们假设它已排序。
同样arr[1]<=arr[2]<=...<=arr[i]
另请注意arr[n] <= arr[i],来自假设。

通过加入上述 3 个不等式,我们得到:

arr[i+1] <= arr[i+2] <= ... <= arr[n] M= arr[1] <= arr[2] <= ... <= arr[i]

根据定义,上面是一个排序数组,它结束了声明的证明。

权利要求 3:

算法正确

通过应用 claim1、claim2 并专门处理数组已经排序的情况,我们得到:

当且仅当以下情况下,可以使用“单位移位”对数组进行排序:它已经排序,或者声明 2 的条件适用,并且证明结束。

QED

【讨论】:

  • 如果我输入1 3 2,那么i的值就是1,按照你的逻辑,答案会是2,然而,实际上述输入的答案是-1。也就是说,它不能按单位班次排序。此外,旋转次数将为n-i-1
  • @Elliot 一个小错误,抱歉。它应该是arr[n] &lt;= arr[1] - 而不是arr[n] &lt; arr[i](请注意,附录中的证明确实使用了正确的不等式)。算法(有这个修复)是正确的,因为我证明了它。
  • @Elliot 另请注意,我使用了基于 1 的索引(即 arr[1] 是第一个元素,而不是 arr[0])(抱歉,如果它令人困惑,最近使用了很多 matlab,它是现在几乎是一种习惯)
  • 荣誉。惊人的证明和写得很好。谢谢您的帮助。非常感激。 :)
猜你喜欢
  • 2017-03-12
  • 2020-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多