资讯专栏INFORMATION COLUMN

编程小结

scwang90 / 3085人阅读

摘要:给定数组,取个数,和为,有哪些种取法递归解法递归优化,计算过程中去重思路一的做法,存在大量的重复,实际上对循环做一点修改,就可以在过程中避免重复迭代砝码问题给一组砝码,给一个重量,问用该组砝码能否称出该重量。

给定数组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语言是面向对象的等等,这个编程模型到处可见,但是始终搞不清是什么?什么语言又是什么编程模型,当你新接触一门语言的时候,有些问题是需...

    miya 评论0 收藏0
  • 编程模型(范式)小结

    摘要:参考链接面向对象编程模型现在的很多编程语言基本都具有面向对象的思想,比如等等,而面向对象的主要思想对象,类,继承,封装,多态比较容易理解,这里就不多多描述了。 前言 在我们的日常日发和学习生活中会常常遇到一些名词,比如 命令式编程模型,声明式编程模型,xxx语言是面向对象的等等,这个编程模型到处可见,但是始终搞不清是什么?什么语言又是什么编程模型,当你新接触一门语言的时候,有些问题是需...

    ShowerSun 评论0 收藏0
  • javascript函数式编程入门小结

    摘要:前言最近花了不少时间接触学习的函数式的编程方式,而后为了加深理解,又去折腾。不过幸运的是,天生具备了函数式编程的基本元素,所以学习的起点不会太低。初接触第一个实例,函数式编程是如何做一个番茄炒鸡蛋的。 前言 最近花了不少时间接触学习javascript的函数式的编程方式,而后为了加深理解,又去折腾haskell。 不同于人们比较熟悉的命令式编程,如面向对象编程(oop),函数式编程(f...

    includecmath 评论0 收藏0
  • Javascript函数式编程小结

    摘要:源起函数式编程近几年非常流行经常可以在网上看到别人讨论相关话题我机缘巧合之下在上看到有人提到一个讲函数式编程的视频看过之后突然茅塞顿开瞬间把之前零碎的关于函数式编程的知识一下子都联系了起来于是自己希望趁有空把这些知识总结一下这样既可以回顾下 源起 函数式编程近几年非常流行,经常可以在网上看到别人讨论相关话题. 我机缘巧合之下在github上看到有人提到一个讲js函数式编程的视频,看过之...

    zengdongbao 评论0 收藏0
  • shell script编程小结——附带实例

    摘要:编程小结前言作为编程中不可或缺的一部分,平日里,我们经常会在中输入一些命令。编程中,用对了指令可以减少许多工作。参考资料教程菜鸟教程命令大全首发地址 shell script编程小结 前言 shell作为编程中不可或缺的一部分,平日里,我们经常会在shell中输入一些命令。有时候也需要完成一些复杂的操作,重复的输入多条相同的命令,过于费时和无趣。所以掌握shell script就显得非...

    idealcn 评论0 收藏0
  • shell script编程小结——附带实例

    摘要:编程小结前言作为编程中不可或缺的一部分,平日里,我们经常会在中输入一些命令。编程中,用对了指令可以减少许多工作。参考资料教程菜鸟教程命令大全首发地址 shell script编程小结 前言 shell作为编程中不可或缺的一部分,平日里,我们经常会在shell中输入一些命令。有时候也需要完成一些复杂的操作,重复的输入多条相同的命令,过于费时和无趣。所以掌握shell script就显得非...

    songjz 评论0 收藏0

发表评论

0条评论

scwang90

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<