有梦想,有干货,微信搜索 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。git
本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试完整考点、资料以及个人系列文章。github
在讲解这道题以前咱们先来看下一个数据结构:栈,由于咱们须要用栈来解决这道题。面试
栈(stack)又名堆栈,它是一种运算受限的线性表,仅在表尾能进行插入和删除操做。这一端被称为栈顶,相对地,把另外一端称为栈底。数组
向一个栈插入新元素又称做进栈、入栈或压栈;从一个栈删除元素又称做出栈或退栈。微信
后进先出(LIFO)特色:栈中的元素,最早进栈的一定是最后出栈,后进栈的必定会先出栈。数据结构
JavaScript中,栈能够用数组模拟。须要限制只能使用push()
和pop()
,不能使用unshift()
和shift()
。即,数组尾是栈顶。函数
固然,能够用面向对象等手段,将栈封装的更好。工具
这是头条和滴滴的一道面试题,题目是这样的:spa
试编写“智能重复”smartRepeat函数,实现:debug
abcabcabc
aabbaabbaabb
abbbcccddddcccddddabbbcccddddcccdddd
不用考虑输入字符串是非法的状况,好比:
你们一看到这题目,应该想到的用递归的方式来作,实际上这道题用递归是比较难的。也是能作,但相比栈,栈的方式会简单的多。
初学者大坑:栈的题目和递归很是像,这类题目给人的感受都是用递归解题。信心满满动手开始写了,却发现递归怎么都递归不出来。此时就要想到,不是用递归,而是用栈。
这道题目咱们可使用两个栈来解,第一个栈存放数字,第二个栈存放字符串
这时候能够发现咱们指针只须要遍历一次就好了,怎么看?
规则是这样的子:遍历到数字就把数字压栈
而后继续遍历,这时遍历到方括号,或者说是遍历到数字和方括号,那么咱们就把另外一个栈放入一个空字符串 ''
。
而后下移,遇到 3,一样也是压栈:
而后下移,遇到方括号了,压入一个空字符串 ''
而后下移,遇到字母 a
,那么遇到字母是什么规则呢,如图中所示:
而后下移,遇到 ]
,注意,遍历到结束的右大括号的时候,是一个很是重要的时间,那这个规则又是啥呢,以下图所示:
是否是有点看不懂了,那么咱们重头在跑一次
而后下移遇到 4[
,分别把数字 4 和 空字符串压入:
而后下移遇到 1[
,分别把数字 1 和 空字符串压入:
而后下移遇到 b
,压入:
而后下移,遇到结束符 ]
,分别要 1 和 'b' 弹出来,此时在把 'b' 重复一遍后拼接到第二个栈顶元素
而后下移,遇到 2,一样的操做:
而后下移遇到 c,直接写入:
而后下移,遇到结束符 ]
,分别把 2 和 'c',弹出,此时在把 'c' 重复二遍后拼接到第二个栈顶元素
而后下移,遇到倒数第二个结束符 ]
,分别把 4 和 'bccc',弹出,此时在把 'bccc' 重复四四遍后拼接到第二个栈顶元素
而后下移,遇到最后一个结束符 ]
,分别把 2 和 'aaabccbccbccbcc',弹出,此时在把 'aaabccbccbccbcc' 重复两遍,这时个就不用拼到上一个元素了,由于已是最后一个了:
这个答案是否是就是咱们最后的答案了,神奇吧~
这时个咱们在按上面的流程来演示一上这题:
2[1[a]3[b]2[3[c]4[d]]]
变为abbbcccddddcccddddabbbcccddddcccdddd
。
建立 index.js
,输入如下内容:
// 试编写“智能重复”smartRepeat函数,实现: // 将3[abc]变为abcabcabc // 将3[2[a]2[b]]变为aabbaabbaabb // 将2[1[a]3[b]2[3[c]4[d]]]变为abbbcccddddcccddddabbbcccddddcccdddd function smartRepeat(templateStr) { // 指针 var index = 0; // 栈1,存放数字 var stack1 = []; // 栈2,存放临时字符串 var stack2 = []; // 剩余部分 var rest = templateStr; while (index < templateStr.length - 1) { // 剩余部分 rest = templateStr.substring(index); // 看当前剩余部分是否是以数字和[开头 if (/^\d+\[/.test(rest)) { // 获得这个数字 let times = Number(rest.match(/^(\d+)\[/)[1]); // 就把数字压栈,把空字符串压栈 stack1.push(times); stack2.push(""); // 让指针后移,times这个数字是多少位就后移多少位加1位。 // 为何要加1呢?加的1位是[。 index += times.toString().length + 1; } else if (/^\w+\]/.test(rest)) { // 若是这个字符是字母,那么此时就把栈顶这项改成这个字母 let word = rest.match(/^(\w+)\]/)[1]; stack2[stack2.length - 1] = word; // 让指针后移,word这个词语是多少位就后移多少位 index += word.length; } else if (rest[0] == "]") { // 若是这个字符是],那么就①将stack1弹栈,②stack2弹栈,③把字符串栈的新栈顶的元素重复刚刚弹出的那个字符串指定次数拼接到新栈顶上。 let times = stack1.pop(); let word = stack2.pop(); // repeat是ES6的方法,好比'a'.repeat(3)获得'aaa' stack2[stack2.length - 1] += word.repeat(times); index++; } console.log(index, stack1, stack2); } // while结束以后,stack1和stack2中确定还剩余1项。返回栈2中剩下的这一项,重复栈1中剩下的这1项次数,组成的这个字符串。若是剩的个数不对,那就是用户的问题,方括号没有闭合。 return stack2[0].repeat(stack1[0]); } var result = smartRepeat("3[2[3[a]1[b]]4[d]]"); console.log(result);
~完,我是小智,刷牛客网去了,咱们下期见~
代码部署后可能存在的BUG无法实时知道,过后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给你们推荐一个好用的BUG监控工具 Fundebug。
有梦想,有干货,微信搜索 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。
本文 GitHub https://github.com/qq44924588... 已收录,有一线大厂面试完整考点、资料以及个人系列文章。