使用Js實現排列組合算法。

前兩天有位技術大牛提了一個他本人很是喜歡問到的面試題,在這裏和你們分享一下題目和個人解答,歡迎各位理智討論。

給出一個數字數組<Number>[], 如[1, 2, 3], 如何打印出全部的排列A33(這裏打不出來上下標,見諒)。 即: 打印出[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]。面試

咱們先來看看排列組合在數學上的概念:數組

排列指的是從n個不一樣元素中,任取m(m≤n,m與n均爲天然數,下同)個不一樣的元素按照必定的順序排成一列,叫作從n個不一樣元素中取出m個元素的一個排列緩存

組合指的是從n個不一樣元素中,任取m(m≤n)個元素併成一組,叫作從n個不一樣元素中取出m個元素的一個組合oop

貼下個人回答:優化

function permutationAndCombination(source = [], selectedLimit, isPermutation = true) {
           if (!Array.isArray(source)) return source

           // remove duplicated item
           source = [...new Set(source)]
           selectedLimit = selectedLimit || source.length

           const result = []
           const sourceLen = source.length

           selectedLimit = selectedLimit > sourceLen ? sourceLen : selectedLimit

           const innerLoop = (prefix = [], done = [], index = 0) => {
               const prefixLen = prefix.length

               for (let i = isPermutation ? 0 : index; i < sourceLen; i++) {

                   if (prefixLen > selectedLimit - 1) break

                   // Optimization: Continue to next cycle if current item has be already used for 'prefix'.
                   if (done.includes(i)) continue

                   const item = source[i]
                   const newItem = [...prefix, item]

                   if (prefixLen === selectedLimit - 1) {
                       result.push(newItem)
                   }

                   if (prefixLen < selectedLimit - 1) {
                       innerLoop(newItem, [...done, i], index++)
                   }

               }
           }

           if (source.length) {

               // there is only one case if we want to select all items from source by combination.
               if (!isPermutation && selectedLimit === sourceLen) {
                   return source
               }

               innerLoop()
           }

           return result
       }

複製代碼

A33: 從3個不一樣元素中取3個元素按必定順序排列

permutationAndCombination([1, 2, 3])
   
複製代碼

結果以下ui


A32: 從3個不一樣元素中取2個元素按必定順序排列

permutationAndCombination([1, 2, 3], 2)
    
複製代碼

結果以下spa


A31: 從3個不一樣元素中取1個元素按必定順序排列

permutationAndCombination([1, 2, 3], 1)
    
複製代碼

結果以下code


重複元素會被忽略掉,遵循排列組合的定義,咱們在方法的開始部分作了去重的操做。

// remove duplicated item
   source = [...new Set(source)]
 
複製代碼
permutationAndCombination([1, 2, 3, 3])
   
複製代碼

結果以下cdn

若是咱們在排列的時候不想忽略重複的,就須要作一個緩存,已經出現的就不須要再次操做了。blog


C33: 從3個不一樣元素中取3個元素無序排列,這種狀況其實只有一種,代碼中作了優化,直接返回源數組。

// there is only one case if we want to select all items from source by combination.
   if (!isPermutation && selectedLimit === sourceLength) {
       return source
   }
   
複製代碼
permutationAndCombination([1, 2, 3], 3, false)
    
複製代碼

結果以下


C32: 從3個不一樣元素中取2個元素無序排列

permutationAndCombination([1, 2, 3], 2, false)
    
複製代碼

結果以下


C31: 從3個不一樣元素中取1個元素無序排列

permutationAndCombination([1, 2, 3], 1, false)
    
複製代碼

結果以下


若是各位有更好的思路,歡迎討論。

相關文章
相關標籤/搜索