給出一個數字數組<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
}
複製代碼
permutationAndCombination([1, 2, 3])
複製代碼
結果以下ui
permutationAndCombination([1, 2, 3], 2)
複製代碼
結果以下spa
permutationAndCombination([1, 2, 3], 1)
複製代碼
結果以下code
// remove duplicated item
source = [...new Set(source)]
複製代碼
permutationAndCombination([1, 2, 3, 3])
複製代碼
結果以下cdn
若是咱們在排列的時候不想忽略重複的,就須要作一個緩存,已經出現的就不須要再次操做了。blog
// 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)
複製代碼
結果以下
permutationAndCombination([1, 2, 3], 2, false)
複製代碼
結果以下
permutationAndCombination([1, 2, 3], 1, false)
複製代碼
結果以下