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)