算法学习记录(四十七)

191 阅读2分钟

问:

  1. 给定一个元素都为整数的二维数组matrix。假设从矩阵的最左侧选一个数作为开始。每次可以选择当前数的右侧、右上、右下的数累加。当某一次累加和小于0或者走到最后一列游戏结束。在选择的过程中,有一次正负替换的机会(即把当前数变为相反数)。问,累加和最多可以是多少。
  2. 给定一个字符串str。str表示一个公式。公式里可能有整数、加减乘除符号和左右括号。返回公式的计算结果。例如:str='48*((70-65)-43)+8* 1',返回-1816

解:

  1. 递归返回两个值,分别是不用正负替换能达到的最大值,用正副替换能达到的最大值。取更大的就可以。
// 暴力递归
function getMaxSum(matrix) {
    let res = 0
    for (let i = 0; i < matrix.length; i++) {
        const { no, yes } = getRes(i, 0)
        res = Math.max(no, yes, res)
    }
    return res
    function getRes(row, col) {
        if (row < 0) return {
            no: 0,
            yes: 0
        }
        if (col === 0) {
            return {
                no: matrix[row][col],
                yes: -matrix[row][col]
            }
        }
        let no = -1
        let yes = -1
        if (row > 0) {
            const leftUp = getRes(row - 1, col - 1)
            if (leftUp.no > 0) no = leftUp.no
            if (leftUp.yes > 0) yes = leftUp.yes
        }
        const left = getRes(row, col - 1)
        if (left.no > 0) no = Math.max(no, left.no)
        if (left.yes > 0) no = Math.max(yes, left.yes)
        if (row < matrix.length - 1) {
            const leftDown = getRes(row + 1, col - 1)
            if (leftDown.no > 0) no = Math.max(no, leftDown.no)
            if (leftDown.yes > 0) no = Math.max(yes, leftDown.yes)
        }
        let curNo = -1
        let curYes = -1
        if (no > 0) {
            curNo = no + matrix[row][col]
            curYes = no - matrix[row][col]
        }
        if (yes > 0) {
            curYes = Math.max(curYes, curYes + matrix[row][col])
        }
        return {
            no: curNo,
            yes: curYes
        }
    }
}
  1. 设定一个临时变量curNum存储数字,遍历str,碰到数字就跟curNum相加,碰到运算符号就判断栈顶是不是乘除。是的话就取出来两个元素跟curNum计算一次,然后把结果加到栈里。如果不是就直接加到栈里。碰到左括号,直接从左括号下一位开始递归这个过程。碰到右括号时结算栈内数据,返回计算结果和位置信息给左括号即可。遍历完毕后结算栈内数据。
function getComputedResult(str) {
    function getRes(i) {
        const stack = []
        let curNum = ''
        let res = 0
        while (i <= str.length) {
            if (['+', '-', '*', '/'].includes(str[i])) {
                curNum = isCount(stack, curNum)
                stack.push(curNum, str[i++])
                curNum = ''
            } else if (['('].includes(str[i])) {
                const { res,idx } = getRes(i + 1)
                curNum = res
                i = idx
            } else if (str[i] === ')' || i === str.length){
                curNum = isCount(stack, curNum)
                stack.push(curNum)
                i++
                // 最后结算栈内全部数据
                res = settlement(stack)
                return {
                    res,
                    idx: i
                }
            } else {
                // 如果是数字
                curNum += str[i++]
            }
        }
    }
    const { res } = getRes(0)
    return res
    // 结算栈内数据
    function settlement(stack) {
        let res = 0
        let fh = ''
        while (stack.length) {
            const cur = stack.shift()
            if (cur !== '+' && cur !== '-') {
                if (fh === '+' || fh === '') res += +cur
                if (fh === '-') res -= +cur
            } else {
                fh = cur
            }
        }
        return res
    }
    function isCount (selfStack, curNum) {
        // 栈顶是否是乘除,是的话计算一次
        const last = selfStack[selfStack.length - 1]
        if (last === '*' || last === '/') {
            const fh = selfStack.pop()
            const num = selfStack.pop()
            curNum = fh === '*' ? +num * curNum : (+num / curNum).toFixed(2)
        }
        return curNum
    }
}