1、素数环:从1到20这20个数摆成一个环,要求相邻的两个数的和是一个素数。
let ans = [], flagArr = []
function primeSum(a, b) {
let sum = a+b, k = 2
for (; k <= Math.sqrt(sum); k++) {
if (!(sum % k)) return false
}
return true
}
function primeRing(num, k=1) {
for (let i = 1; i < num+1; i++) {
if (!flagArr[i-1] && primeSum(ans[k-1], i)) {
flagArr[i-1] = 1
ans[k] = i
if (k == num-1) {
if (primeSum(ans[num-1], ans[0])) console.log(ans)
} else {
primeRing(num, k+1)
}
flagArr[i-1] = 0
}
}
}
for (let i=1; i <= 20; i++) {
ans[0] = i
flagArr[i-1] = 1
primeRing(20)
flagArr[i-1] = 0
}这样得到的结果数量除以20才是符合要求的环的数量,暂时不作去重
2、设有n个整数的集合{1,2,...,n},从中任意取出r个数进行排列(r<n),试列出所有的排列。
let ans = [], flagArr = []
function allRank(n, k=1) {
for (let i = 1; i < n+1; i++) {
if (!flagArr[i-1]) {
flagArr[i-1] = 1
ans.push(i)
if (k === n) console.log(ans)
else allRank(n, k+1)
flagArr[i-1] = 0
ans.pop()
}
}
}
//test
allRank(5)3、任何一个大于1的自然数n,总可以拆分成若干个小于n的自然数之和。求所有拆分方法。
let target = 5, ans = [1] // 记住这个1
function splitANum(num) {
// i取值为当前数组的最后一项,保证结果数组的每一项递增,从而使最后得到的所有拆分方法不重复;i小于等于num以保证num-i不小于0
for (let i = ans[ans.length-1]; i <= num; i++) {
if (i == target) return // 拆分项不允许等于拆分目标
ans.push(i)
num -= i
if (num == 0) { //拆分完毕,打印结果
console.log(ans.slice(1)) //去掉最开始的1
}
else splitANum(num) //继续拆分
// 游戏回档
ans.pop()
num += i
}
}
//test
splitANum(target)


京公网安备 11010502036488号