使用分治法實現的全排列演算法

來源:互聯網
上載者:User
我們將使用分治法實現一個全排列演算法。先來看一下演算法實現後的效果:['a','b','c'].permutation        #=> [["a", "b", "c"],

#                                     ["a", "c", "b"],

#                                     ["b", "a", "c"],

#                                     ["b", "c", "a"],

#                                     ["c", "a", "b"],

#                                     ["c", "b", "a"]]

演算法描述

分治法求解問題分為三個步驟:
    - 分解:將問題分為若干個子問題。
    - 解決:遞迴地求解每個子問題。
    - 合并:將每個子問題的解合并成為整個問題的解。

現在我們需要求具有n個元素的數組A的全排列。例如:大小為3的數組A=[a,b,c] (為方便起見,我把引號全都省略了,其實應該是A=['a','b','c']。下同),它的全排列為:
[[a,b,c],
 [a,c,b],
 [b,a,c],
 [b,c,a],
 [c,a,b],
 [c,b,a]]
這是一個大小為 n!*n 的二維數組。

使用分治演算法求解全排列的過程如下
    - 分解:將數組分為子數組 A[1..k-1] 和一個元素 A[k]。 (1≤k≤n)
    - 解決:遞迴地求解每個子數組 A[1..k-1] 的全排列,直至子數組A[1..k-1]為空白時結束遞迴。
    - 合并:將上一步的結果---A[1..k-1]的全排列(一個二維數組)與元素A[k]合并,得出A[1..k]的全排列。例如:
                   [[]] 與 a 合并得到 [[a]]
                   [[a]] 與 b 合并得到 [[a,b], [b,a]]
                   [[a,b],[b,a]] 與 c 合并得到 [[a,b,c],[a,c,b],[c,a,b],[b,c,a],[c,a,b],[c,b,a]]

看下面的圖示會更直觀一些

1. 分解過程        [a,b,c]        

       /       \       

   [a,b]         c     

   /   \       

  [a]    b  
  / \
 []  a

2. 合并過程[]    a

  \  /

  [[a]]      b

      \   /

  [[a,b],[b,a]]    c

             \   /

             [[a,b,c],

              [a,c,b],

              [c,a,b],

              [b,a,c],

              [b,c,a],

              [c,b,a]]

原始碼

下面是ruby的原始碼(檔案名稱“permutation.rb”)class Array
  # Returns permutation(a new two-dimentional array) of self.
  # Example
  #    - [].permutation  #=> [[]]
  #    - ['A'].permutation  #=> [['A']]
  #    - ['A','B'].permutation  #=> [['A','B'],['B','A']]
  #    - ['A','B','C'].permutation  #=>  [['A','B','C'],
  #                                               ['A','C','B'],
  #                                               ['B','A','C'],
  #                                               ['B','C','A'],
  #                                               ['C','A','B'],
  #                                               ['C','B','A']]
  def permutation()
    permutation_i(self.length-1).sort!
  end
  
  private
  
  def permutation_i(i)
    if i> 0
      return Array.merge_permutation(permutation_i(i-1), self[i])
    else
      return Array.merge_permutation([[]], self[i])
    end
  end
  
  # Example
  #    - Array.merge_permutation([[]], 'A')  #=> [['A']]
  #    - Array.merge_permutation([['A']], 'B')  #=> [['B','A'],['A','B']]
  #    - Array.merge_permutation([['B','A'],['A','B']], 'C')  #=> [['C','B','A'],
  #                                                                               ['B','C','A'],
  #                                                                               ['B','A','C'],
  #                                                                               ['C','B','A'],
  #                                                                               ['A','C','B'],
  #                                                                               ['A','B','C']]
  def Array.merge_permutation(src, item)
    result = Array.new
    src.each do |each_array|
      result += Array.item_permutation(each_array, item)
    end
    
    return result 
  end
  
  # Returns a new two-dimentional array. Inserts "item" in each pertential place in "src".
  # Example
  #    - Array.item_permutation([], 'A')  #=> [['A']]
  #    - Array.item_permutation(['A'], 'B')  #=> [['B','A'], ['A','B']]
  #    - Array.item_permutation(['A','B'], 'C')  #=> [['C','A','B'], ['A','C','B'], 'A','B','C']]
  def Array.item_permutation(src, item)
    result = Array.new
    (0..src.length).each do |i|
      new_array = src.collect
      new_array.insert(i, item)
      result << new_array
    end
    
    return result
  end
end

require 'pp_extension'
pp(['a','b','c'].permutation)

原始碼用於輸出二維數組的“pp_extension”可以看我的這篇文章讓ruby以矩陣的樣式輸出二維數組
原始碼如下(檔案名稱"pp_extension.rb")require 'pp'
# Outputs two-dimension array like matrix
class Array
  def pretty_print(q)
    q.group(1, '[', ']') {
      q.seplist(self) {|v|
        q.current_group.break if v.is_a?(Array) && !q.current_group.first?  # added by me
        q.pp v
      }
    }
  end
end

已耗用時間

演算法已耗用時間 T(n) = T(n-1) + Θ(n2) = Θ(n3)

注 本文並不是從教科書上抄下來的,而是我閉門造車的結果,所以很可能有不正之處,請不吝賜教。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.