摘要:给定数组,取个数,和为,有哪些种取法递归解法递归优化,计算过程中去重思路一的做法,存在大量的重复,实际上对循环做一点修改,就可以在过程中避免重复迭代砝码问题给一组砝码,给一个重量,问用该组砝码能否称出该重量。
给定数组arr,取n个数,和为sum,有哪些种取法 递归解法
function main(arr, sum, n) { let result = [] if (n === 1) { arr.filter(item => item === sum) .forEach(item2 => result.push([item2])) return result } for (let i = 0; i < arr.length; i++) { let el = arr[i] let subArr = arr.slice() subArr.splice(i, 1) let subResult = main(subArr, sum - el, n - 1) if (subResult.length > 0) { subResult.forEach(item3 => { item3.unshift(el) result.push(item3) }) } } return result } let result = main([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 18, 3) let result2 = result.map(item => item.sort().join(",")) console.log([...new Set(result2)])递归优化,计算过程中去重
思路一的做法,存在大量的重复,实际上对 for 循环做一点修改,就可以在过程中避免重复
function main(arr, n, sum) { if (n === 1) { return arr.includes(sum) ? [ [sum] ] : [] } let result = [] for (let i = 0; i < arr.length - n; i++) { let arr1 = arr.slice(i + 1) let addend = arr[i] let arr2 = main(arr1, n - 1, sum - addend) arr2.forEach(r => { r.unshift(addend) result.push(r) }) } return result } let result = main([1, 2, 3, 4, 5, 6, 7, 8, 9], 3, 15) debugger迭代
function main(arr, n, sum) { let result = [] let step = 1 let stack = [{ sum: [], arr }] while (step < n) { let newStack = [] stack.forEach(s => { for (let i = 0; i < s.arr.length; i++) { let newSum = [...s.sum, s.arr[i]] if (newSum.reduce((a, b) => a + b, 0) < sum) { newStack.push({ sum: newSum, arr: s.arr.slice(i + 1) }) } } }) stack = newStack step++ } stack.forEach(s => { for (let i = 0; i < s.arr.length; i++) { let newSum = [...s.sum, s.arr[i]] if (newSum.reduce((a, b) => a + b, 0) === sum) { result.push([...s.sum, s.arr[i]]) } } }) return result } let result = main([1, 2, 3, 4, 5, 6, 7, 8, 9], 3, 15) debugger砝码问题
给一组砝码,给一个重量,问用该组砝码能否称出该重量。例如,一组砝码 [1,3],一个重量 2,返回 true
递归function main(arr, weight) { // 终止条件 if (arr.length === 0) { return false } if (arr.length === 1) { return arr[0] === weight ? true : false } if (arr.includes(weight)) { return true } let item = arr[0] if (main(arr.slice(1), weight)) { return true } if (main(arr.slice(1), weight + item)) { return true } if (main(arr.slice(1), weight - item)) { return true } return false } let result = main([1, 2, 10], 6) debugger迭代
function main(arr, weight) { let stack = [0] let i = 0 while (i < arr.length) { let stackCopy = [] for (let j = 0; j < stack.length; j++) { let s = stack[j] if (s === weight) { return true } if (s + arr[i] === weight) { return true } if (s - arr[i] === weight) { return true } stackCopy.push(s + arr[i]) stackCopy.push(s - arr[i]) stackCopy.push(s) } stack = stackCopy i++ } return false } let result = main([1, 2, 10], 3) debugger+1,*2计算最少步数
给一个数,只能从1开始,+1或者*2,问最少多少步可以达到这个数
function main(x) { let result = [] result.push(Math.ceil(x / 2)) // 7 => (1+1+1)*2+1 共4步 // 12 => (1+1+1+1+1+1)*2 共6步 let i = 1 let count = 0 while (i * 2 <= x) { i = i * 2 count++ } count = count + x - i result.push(count) return result // 用 +1 的方法,步数始终是 Math.ceil(x/2) // 用 *2 后 +1 的方法,主要是考虑当 2^(n+1) > x > 2^n 时,从 2^n 到 x 需要进行多少次 +1 } let result = main(15) debugger斐波那契数列 传统递归方法
function fib1(n) { if (n < 2) { return n } return fib1(n - 1) + fib1(n - 2) } console.log(fib1(10))迭代
function fib2(n) { if (n < 2) { return n } let arr = [0, 1] for (let i = 2; i < n + 1; i++) { arr.push(arr[i - 1] + arr[i - 2]) } return arr[n] } console.log(fib2(10))迭代优化
function fib3(n) { if (n < 2) { return n } let arr = [0, 1] for (let i = 2; i < n; i++) { let sum = arr[0] + arr[1] arr[0] = arr[1] arr[1] = sum } return arr[0] + arr[1] } console.log(fib3(10))递归优化一
function fib4(n, p, k) { if (n === 1) { return k } if (n === 0) { return p } return fib4(n - 1, k, p + k) } console.log(fib4(10, 0, 1))递归优化二
function fib5(n, p, k) { if (n === 1) { return k } if (n === 0) { return p } return fib5(n - 2, p + k, p + k + k) } console.log(fib5(10, 0, 1))一点感悟
迭代是自下而上,递归是自上而下
求 0,1,1,2,3,5,8,13,21,34,55 的fib4(10)
等于求 1,1,2,3,5,8,13,21,34,55 的fib4(9)
等同于求 1,2,3,5,8,13,21,34,55 的fib4(8)
每递归调用一次,都自下而上计算一次
递归的关键还是在于如何划分子问题,确定子问题与父问题之间的关系
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/93561.html
摘要:参考链接面向对象编程模型现在的很多编程语言基本都具有面向对象的思想,比如等等,而面向对象的主要思想对象,类,继承,封装,多态比较容易理解,这里就不多多描述了。 前言 在我们的日常日发和学习生活中会常常遇到一些名词,比如 命令式编程模型,声明式编程模型,xxx语言是面向对象的等等,这个编程模型到处可见,但是始终搞不清是什么?什么语言又是什么编程模型,当你新接触一门语言的时候,有些问题是需...
摘要:前言最近花了不少时间接触学习的函数式的编程方式,而后为了加深理解,又去折腾。不过幸运的是,天生具备了函数式编程的基本元素,所以学习的起点不会太低。初接触第一个实例,函数式编程是如何做一个番茄炒鸡蛋的。 前言 最近花了不少时间接触学习javascript的函数式的编程方式,而后为了加深理解,又去折腾haskell。 不同于人们比较熟悉的命令式编程,如面向对象编程(oop),函数式编程(f...
摘要:源起函数式编程近几年非常流行经常可以在网上看到别人讨论相关话题我机缘巧合之下在上看到有人提到一个讲函数式编程的视频看过之后突然茅塞顿开瞬间把之前零碎的关于函数式编程的知识一下子都联系了起来于是自己希望趁有空把这些知识总结一下这样既可以回顾下 源起 函数式编程近几年非常流行,经常可以在网上看到别人讨论相关话题. 我机缘巧合之下在github上看到有人提到一个讲js函数式编程的视频,看过之...
阅读 3071·2021-10-11 10:58
阅读 1988·2021-09-24 09:47
阅读 502·2019-08-30 14:19
阅读 1682·2019-08-30 13:58
阅读 1443·2019-08-29 15:26
阅读 639·2019-08-26 13:45
阅读 2138·2019-08-26 11:53
阅读 1771·2019-08-26 11:30