最小交换次数的正确性对数组进行排序

时间:2018-01-29 11:34:10

标签: algorithm sorting correctness

问题来自:https://www.geeksforgeeks.org/minimum-number-swaps-required-sort-array/

我将在下面重复: 给定n个不同元素的数组,找到对数组进行排序所需的最小交换次数。

示例:

输入:{4,3,2,1} 输出:2 说明:将索引0与3交换,1与2交换               形成排序数组{1,2,3,4}。

输入:{1,5,4,3,2} 输出:2

我通过以下方式解决了这个问题。

  1. 对数组进行排序(n log(n))时间
  2. 制作哈希以跟踪所需的交换,因为我比较了已排序的数组和原始数组。这应该是另一个O(n)时间
  3. 总时间复杂度应为:O(n +(n log n))= O(n log(n))

    以下是我为此编写的代码,它适用于所提供的测试用例。

    def solution(array)
    
      sorted = array.sort
      puts array.inspect
      puts sorted.inspect
    
      counter_parts_that_have_been_seen = {}
    
      number_of_swaps_required = 0
    
      array.each_with_index do | val, idx |
        if counter_parts_that_have_been_seen[val] == true
          next
        end
    
        array_val = val
        sorted_val = sorted[idx]
    
        if array_val != sorted_val
          puts "A swap will be required: array val is #{array_val} and sorted_array_val is #{sorted_val}"
          number_of_swaps_required += 1
          counter_parts_that_have_been_seen[sorted_val] = true
        end
      end
    
      puts "Number of swaps required are: #{number_of_swaps_required}"
    
    end
    

    现在,我的问题是,如何验证正确性?我没有天气感,这种方法是正确的。

    有人可以对此有所了解吗?

3 个答案:

答案 0 :(得分:0)

从未排序数组中的第一个元素开始,检查它是否在正确的位置,如果没有将正确的值交换到该位置。测试可以通过与集合的排序版本进行比较来完成,也可以将所选元素与其后面的每个元素进行比较。

随着你的进展,你可能会遇到处于正确位置的元素 - 要么是因为它们在正确的位置开始,要么在放置一个早期元素时交换它们(最后一个元素必须在所有其他元素被放置的时候)放置)。只需将它们留在原地并转移到下一个元素。

使用此方法,每个交换都会正确放置至少一个元素,某些交换将正确放置两个元素。

正确位置的元素可以从问题中打折扣 - 从来没有必要将其从正确的位置移动以对任何其他元素进行排序。 另外一对元素(例如{3,2,1}中的3和1)永远不需要与任何其他元素交换。它们形成了自己独立的元素。

如果你有一个方法,如上所述,为了获得正确的答案,它显然可以用来评估任何替代方法。

答案 1 :(得分:0)

Index :   0   1   2   3   4   5   6   7   8   9
------+-----+---+---+---+---+---+---+---+---+--
Array :   1  22  32  42  12  83  64  93  73  53
------+-----+---+---+---+---+---+---+---+---+--
          A  BBBBBBBBBBBBBB  CC  DD  CCCCCCCCCC
Target:   0   2   3   4   1   8   6   9   7   5
Diffs :   0   1   1   1  -3   3   0   2  -1  -4
Source:   0   4   1   2   3   9   6   8   5   7

在此示例中,需要对数组[]进行排序。

  • 目标是排序
  • 后该位置的索引
  • source是此索引从
  • 获取其值的位置
  • diffs是此索引中的项目在排序期间执行的相对移动

您可以看到四个(循环)组:

  • 答:1名成员1
  • B:4名成员{22,32,42,12}
  • C:4名成员:{83,93,73,53}
  • D:1名成员:64

具有1个成员的组已经排序:需要零交换。 具有4个成员的组可以按每个4个交换进行排序。 (最终交换将两个元素放到最后的位置) 因此,所需的掉期数量为 0 + 3 + 3 + 0

现在你只需要证明你可以在N-1掉期中对N周期进行排序......

答案 2 :(得分:0)

如果有一个元素不在正确的位置,那么一定还有另一个元素不在它的正确位置(第一个元素需要放在被另一个元素占据的其他位置) .如果这以图形的形式表示,则没有正确元素的位置将有一条边朝向它,一条边则从它开始。这将最终形成一个或多个循环。现在,循环中元素的位置都在该循环内。因此,我们现在需要证明如果循环中有“n”个元素,则需要最少的“n-1”次交换来对它们进行排序。 我们可以证明这是归纳法。

基数:n=1
只有一个元素,所以已经排序(微不足道)。这意味着 0 次交换,即 n-1 => 1-1 = 0

假设一个循环中有 k 个元素,则需要最少 k-1 次交换

k+1 个元素
循环中的元素具有朝向它需要的位置的边缘。这个位置有另一个朝向其他位置的边缘。现在,如果我们交换前一个元素,我们将删除前一个边缘,后一个元素进入交换位置。现在我们剩下一个大小为 (k+1)-1 = k 的循环。通过归纳,k 个周期需要 k-1 次交换。因此,k+1 将需要 (k-1)+1 = k 次交换。 Initial cycle(k) After one swap (k)