八: 爬楼梯有一个楼梯 , 你一次只能往上走一阶或者两阶 。请编写函数 climbStairs , 它接受一个整数 n 作为参数 , 表示这个楼梯有多少阶 。请你返回一个整数 , 表示这个楼梯一共有多少种走法 。例如:
climbStairs(1) // => 1climbStairs(2) // => 2climbStairs(3) // => 3climbStairs(10) // => 89答案:
// const memorize = [0, 1, 2]// const climbStairs = n => n in memorize ? memorize[n] : (memorize[n] = climbStairs(n - 1) + climbStairs(n - 2))const map = new Map();const climbStairs = (n) => { if (n <= 2) return n; if (map.has(n)) return map.get(n); const stairs = climbStairs(n - 1) + climbStairs(n - 2) map.set(n, stairs); return stairs;}九:奇怪的表达式我们来定义一种新的表达式来表示二元操作:(操作符 操作数 操作数) 。例如原来的 1 + 2 现在我们写成 (+ 1 2);原来的 2 / 1 写成 (/ 2 1) 。表达式里面的操作数可以是另外一个表达式 , 例如:(* 3 (+ 2 1)) 相当于 3 * (2 + 1) 。
请你完成一个函数 runExpression 它可以分析 + - * / 四种简单的二元操作(只操作正整数)并且返回表达式执行的结果 。例如:
【懂这10道JS经典算法题,你就是前端大神】runExpression('(+ 1 2)') // => 3runExpression('(+ (- 2 1) (* 3 (/ 2 1)))') // => 7遇到无法分析情况返回 null 即可 , 例如 runExpression('Hello World') 和 runExpression('5') 则返回 null
答案:
const LEFT_PARENT = 0const RIGHT_PARENT = 1const OPERATOR = 2const OPERANT = 3function runExpression (exp) { try { return run(parse(tokenize(exp))) } catch (e) { return null }}function tokenize(exp) { const tokens = [] let i = 0 let numStr = '' let isNum = false while (i < exp.length) { const char = exp[i++] if (char.match(/d/)) { numStr = isNum ? numStr + char : char isNum = true continue } else if (isNum) { tokens.push({ type: OPERANT, value: numStr * 1 }) isNum = false numStr = '' } if (char === '(') { tokens.push({ type: LEFT_PARENT, value: char }) } else if (char === ')') { tokens.push({ type: RIGHT_PARENT, value: char }) } else if (char.match(/[+-*/]/)) { tokens.push({ type: OPERATOR, value: char }) } else if (char.match(/s/)) { continue } else { throw new Error(`Unexpected token ${char}`) } } if (numStr) tokens.push({ type: OPERANT, value: numStr * 1 }) return tokens}function parse (tokens) { let i = 0 function parseExpression () { /* 仍然是表达式 */ eat(LEFT_PARENT) const node = {} node.operator = parseoperator() node.left = parseOperant() node.right = parseOperant() eat(RIGHT_PARENT) return node } function parseOperant () { /* 最底层数组 */ const current = tokens[i] if (current.type === OPERANT) { eat(OPERANT) return current.value } else { return parseExpression() } } function parseOperator () { const token = eat(OPERATOR) return token.value } function eat (type) { const token = tokens[i] if (token.type !== type) { throw new Error(`Parse error: Unexpected token ${token.value}`) } i++ return token } /* 分析根结点 */ const root = parseExpression() /* 有剩余 token , 表达式不正确 */ if (i !== tokens.length) { const token = tokens[i] throw new Error(`Parse error: Unexpected token ${token.value}`) } return root}function run (ast) { if (typeof ast === 'number') return ast const ops = { '+': (a, b) => a + b, '-': (a, b) => a - b, '*': (a, b) => a * b, '/': (a, b) => a / b } return ops[ast.operator](run(ast.left), run(ast.right))}十:你会被谷歌拒绝吗?Max Howell 参加了谷歌的面试 , 出题人竟然要求 Max Howell 在白板上作出解答 , Max Howell 当然愤怒地拒绝了 , 回家以后马上在微博上跟我们分享他的吐槽:
google: 90% of our engineers use the software you wrote (Homebrew), but you can’t invert a binary tree on a whiteboard so fuck off.
看来在白板上作出反转二叉树的解答并不容易呢?那么在 ScriptOJ 有上 OJ 系统会不会更方便一些呢?
假如有这样一个二叉树 ,
4 /3 2 //7 1 2 3 // 6 5 9使用广度优先的原则用数组的表示就是 [4, 3, 2, 7, 1, 2, 3, 6, 5, 9, null, null, null, null, null] , 二叉树中的空位用 null 表示 。
进行反转以后会变成
4 /2 3 //3 2 1 7/9 5 6使用广度优先的原则用数组的表示就是 [4, 2, 3, 3, 2, 1, 7, null, null, null, null, null, 9, 5, 6] 。
请实现函数 invertTree , 它接受一个表示二叉树的数组 , 返回表示这个反转二叉树的数组 。
请注意 , 提交后提示中显示的 1,2,3,,,4,5 表示的是 1, 2, 3, null, null, 4, 5 。
答案:
const parseTree = (tree) => { if(tree.length <= 3) { const [root, left, right] = tree return [root, [right], [left]] } const left = [] const right = [] let floor tree.slice(1).forEach((value, index) => { floor = ~~(Math.log(index + 2) / Math.LN2) if (left.length < Math.pow(2, floor) - 1) { left.push(value) } else { right.push(value) } }) return [tree[0], parseTree(right), parseTree(left)]}const flatTree = (tree) => { if (tree.every(node => !Array.isArray(node))) return tree const roots = tree.filter(node => !Array.isArray(node)) const children = tree.filter(node => Array.isArray(node)).reduce( (children, child) => children.concat(child), []) return roots.concat(flatTree(children))}const invertTree = (tree) => { const parsedInvertedTree = parseTree(tree) return flatTree(parsedInvertedTree)}
推荐阅读
- 剖析5大自媒体平台,让你清楚知道自媒体变现技巧!
- 日本茶道之源杭州余杭径山茶举行茶祖祭典活动
- 北京环球影城从哪买预售门票 北京环球影城城市大道要门票吗
- LV 经典款围巾大合集
- 史上最经典的10部战争影片
- 出行身份证丢了咋办?
- 你知道人体的脂肪是怎么来的吗?
- 不知道NBA球队这几个规则,你可能是伪球迷,赶紧来补课
- 酒店的取电开关是什么原理?这几种开关只有老师傅才知道
- 除了头孢,吃了这7类药物后饮酒也会致命!越早知道越好