最近公司内部在开始作前端技术的技术分享,每周一个主题的 每周一练,以基础知识为主,感受挺棒的,跟着团队的大佬们学习和复习一些知识,新人也能够多学习一些知识,也把团队内部学习氛围营造起来。 前端
我接下来会开始把每周一练的题目和知识整理一下,便于思考和巩固,就像今天这篇开始。 git
学习的道路,很漫长,要坚持,但愿你们都能掌握本身喜欢的技术,和本身须要的技术。es6
欢迎查看个人 我的主页 && 我的博客 && 我的知识库 && 微信公众号“前端自习课”
本周练习内容:数据结构与算法 —— Stack github
这些都是数据结构与算法,一部分方法是团队其余成员实现的,一部分我本身作的,有什么其余实现方法或错误,欢迎各位大佬指点,感谢。算法
push(element)
:添加一个新元素到栈顶。pop()
:移除栈顶的元素,同时返回被移除的元素。peek()
:返回栈顶的元素,不对栈作任何修改 (这个方法不会移除栈顶的元素,仅仅返回它)。isEmpty()
:若是栈没有任何元素就返回 true
,不然返回 false
。clear()
:移除栈里面的全部元素。size()
:返回栈里的元素个数。这个方法与数组的 length
属性相似。方法1:ES6实现数组
class Stack { constructor (){ this.items = [] } push( element ){ this.items.push(element) } pop(){ return this.items.pop() } peek(){ return this.items[this.items.length - 1] } isEmpty(){ return this.items.length === 0 } clear(){ this.items = [] } size(){ return this.items.length } }
上面实现的方式虽然简单,可是内部 items
属性是公共的,为了知足面向对象变成私有性的原则,咱们应该让 items
做为私有属性,所以咱们可使用 ES6 中 Symbol
或 WeakMap
来实现: 微信
方法2:使用 ES6 的 Symbol 基本数据类型实现
知识点复习:ES6 中的 Symbol 介绍数据结构
const _items = Symbol() class Stack { constructor (){ this[_items] = [] } push (element){ this[_items].push(element) } // 剩下方法和第一种实现的差很少,这里省略 // 只要把前面方法中的 this.items 更改成 this[_items] }
方法3:使用 ES6 的 WeakMap 实现
知识点复习:ES6 中的 WeakMap 介绍函数
const items = new WeakMap() class Stack { constructor (){ items.set(this, []) } push (element){ let item = items.get(this) item.push(element) } // 剩下方法和第一种实现的差很少,这里省略 // 只要把前面方法中的获取 this.items 的方式,更改成 items.get(this) 获取 }
题目意思很简单,就是十进制转二进制,可是在实际工做开发中,咱们更愿意实现的是任意进制转任意进制,不过呢,咱们仍是以解决问题为首要目标呀。 学习
固然,业务需求能够直接使用 toString(2)
方法,可是为了练习,咱仍是不这么用咯。
方法1:使用前面定义的 Stack 类
这里使用前面题目中定义的 Stack
类。
/** * 十进制转换为二进制 * @param {Number} bit */ function bitset (bit){ if(bit == 0) return '0' if(!/^[0-9]+.?[0-9]*$/.test(bit)){ return new Error('请输入正确的数值!') } let stack = new Stack(), result = '' while (bit > 0){ stack.push(bit % 2) bit = Math.floor(bit / 2) } while (!stack.isEmpty()){ result += stack.pop().toString() } return result }
方法2:简单实现
下面这个方法,其实不太好,由于没有怎么用到此次要练习的栈方法,哈哈。
/** * 十进制转换为二进制 * @param {Number} bit */ function bitset (bit){ if(bit == 0) return '0' if(!/^[0-9]+.?[0-9]*$/.test(bit)){ return new Error('请输入正确的数值!') } let arr = [] while(bit > 0){ arr.push(bit % 2) bit = Math.floor(bit / 2) } return arr.reverse().join('') }
另外能够参考:wikiHow - 从十进制转换为二进制。
主要目的就是:该函数接收一个圆括号字符串,判断里面的括号顺序是否有效,若是有效则返回 true
反之 false
。
如:
(
-> false
()
-> true
(()
-> false
())
-> false
())
-> false
(((()()))())
-> true
这个题目实现的主要方法是:遍历字符串,先排除错误状况,而后将 (
入栈保存,将 )
入栈匹配前一个元素是不是 (
,若是是,则 pop()
前一个元素 (
,若是不是,则 push()
这个 )
入栈,最终查看栈是否为空,如果则检验成功,不然失败。
方法1:使用前面定义的 Stack 类
这里使用前面题目中定义的 Stack
类。
/** * 检验圆括号顺序的有效性 * @param {String} str */ function validParentheses (str){ if(!str || str.length === 0 || str[0] === ')') return false let stack = new Stack() str.split('').forEach(char => { let status = stack.peek() === '(' && char === ')' status ? stack.pop() : stack.push(char) }) return stack.isEmpty() }
方法2:出入栈操做
/** * 检验圆括号顺序的有效性 * @param {String} str */ function validParentheses (str){ if(!str || str.length === 0 || str[0] === ')') return false let arr = [] for(let i = 0; i < str.length ; i++){ str[i] === '(' ? arr.push(str[i]) : arr.pop() } return arr.length === 0 }
步骤 | 数据栈 | 辅助栈 | 最小值 |
---|---|---|---|
1.push 3 | 3 | 0 | 3 |
2.push 4 | 3, 4 | 0, 0 | 3 |
3.push 2 | 3, 4, 2 | 0, 0, 2 | 2 |
4.push 1 | 3, 4, 2 ,1 | 0, 0, 2, 3 | 1 |
5.pop | 3, 4, 2 | 0, 0, 2 | 2 |
6.pop | 3, 4 | 0, 0 | 3 |
7.push | 3, 4 ,0 | 0, 0, 2 | 0 |
使用示例以下:
let stack = new Stack(); stack.push(3); console.log('After push 3, Min item is', stack.min()); stack.push(4); console.log('After push 4, Min item is', stack.min()); stack.push(2); console.log('After push 2, Min item is', stack.min()); stack.push(1); console.log('After push 1, Min item is', stack.min()); stack.pop(); console.log('After pop, Min item is', stack.min()); stack.pop(); console.log('After pop, Min item is', stack.min()); stack.push(0); console.log('After push 0, Min item is', stack.min());
提示:利用辅助栈(Web 端可利用数组),每次对栈 push/pop 元素时,也同时更新辅助栈(存储最小元素的位置)
方法1:小操做
class Stack { constructor() { this.items = []; this.minIndexStack = []; } push(element) { this.items.push(element); let minLen = this.minIndexStack.length; let minItemIndex = this.minIndexStack[minLen - 1]; if(minLen === 0 || this.items[minItemIndex] > item) { this.minIndexStack.push(this.items.length - 1); } else { this.minIndexStack.push(minItemIndex); } } pop() { this.minIndexStack.pop(); return this.items.pop(); } min() { let len = this.minIndexStack.length; return (len > 0 && this.items[this.minIndexStack[len - 1]]) || 0; } peek() { return this.items[this.items.length - 1]; } // 省略其它方法 }
方法2:与方法1中push实现的差别
class Stack { constructor (){ this.items = [] // 数据栈 this.arr = [] // 辅助栈 } push( element ){ this.items.push(element) let min = Math.min(...this.items) this.arr.push( min === element ? this.size() - 1 : 0) } pop(){ this.arr.pop() return this.items.pop() } peek(){ return this.items[this.items.length - 1] } isEmpty(){ return this.items.length === 1 } clear(){ this.items = [] } size(){ return this.items.length } min (){ let last = this.arr[this.arr.length - 1] return this.items[last] } }
下周将练习队列(Queue) 的题目,开始翻起算法书籍学习咯。