原文地址javascript
无心间发现 LeetCode 这个网站,一会儿就陷进去了,大学时候看舍友参加 acm 一天到晚刷题,对算法总有点特殊的情怀。本觉得我永远是接触不到这个了,没想到 leetcode 却让我感受到 Accepted 这个单词的特殊魅力。java
首先本身并非为了找工做去刷题的,纯粹享受作题的过程和ac的快感。题目所有用 JavaScript
作的,基本上天天一题的节奏。开始老是想着怎么把答案解出来就好,常常 TLE ,感受一路作下来本身慢慢会考虑复杂度,逻辑严谨性也在逐步增强,对特殊值的考虑愈来愈多,相比于算法能力的提高我更欣喜看到本身逻辑严谨性增强,感受这对本身后面的道路帮助会很大。面试
这里记录本身对一些题目的思路和想法正则表达式
`算法
1 => true; 21 => false; 303 => true;
`json
数字回文,说不能用额外的空间一会儿懵逼了,第一律念就是换成字符串比较,可是感受这样子作就没有意义了。看了别人思路发现给的数字每次取 10 的余数拼起来正好是数字倒过来写。若是只取出一半,原数字也舍弃一半 正好就是回文的两个内容。有了思路就好作了判断下特殊条件,比较最后两个数字就能够了,若是是奇数位数字就减掉中间一位再比较。数组
var max = Math.pow(2,31) - 1 var isPalindrome = function(x) { if (x < 0 || x > max || (x != 0 && x % 10 == 0)) return false if (x < 10) return true var num = 0 while(x > num) { num = num * 10 + x % 10 x = Math.floor(x / 10) } return num == x || (x != 0 && Math.floor(num / 10) == x) };
`函数
给定一个数组,想象成一个二位坐标系,数组中每个元素 a[i] => n 就是坐标系上的一条线段[ (i,0) => (i,x) ]。找出任意两条线段与 x 轴组成的木桶,能够盛水最大的值。
`网站
看到题目想了一下就想着两层循环去计算,果真就超时了,看了看别人的思路,开始就算出0到最后一个线段组成的木桶的面积,而后找出线段比较短的一条向中间靠拢,若是下一条线段比当前线段还短就忽略,反之就继续循环计算。想了想这样作也是合理的若是下一条线段比当前的还短那组成的面积确定比较小。有了思路就好作了spa
var maxArea = function(height) { let i = 0, l = height.length -1, res = 0 while(i < l) { var h = Math.min(height[i],height[l]) res = Math.max(res, (l-i) * h) if(height[i] < height[l]) { while(height[i] <= h && i < l){i++} } else { while(h >= height[l] && i < l){l--} } } return res }
`
实现正则, '.' Matches any single character. '*' Matches zero or more of the preceding element. isMatch("aa","a") → false isMatch("ab", ".*") → true isMatch("aab", "c*a*b") → true
`
刚开始看到这题目仍是比较懵的,感受要判断的好多,后面从递归判断作就有思路了,从正则表达式入手,先判断第二位是否是 * ,若是不是就判断第一位而后截取一位递归,若是是就先去除正则前两位递归,不行再判断第一个是否是相等而后循环递归
var isMatch = function(s, p) { if(p[0] === undefined) return s[0] === undefined if (p[1] != '*') { if (s[0] === p[0] || (p[0] === '.' && s[0] !== undefined)) return isMatch(s.substr(1), p.substr(1)) else return false } else { if (isMatch(s, p.substr(2)))return true let index = 0 while(index <= s.length && (s[index] === p[0] || p[0] === '.')){ if(isMatch(s.substr(++index), p.substr(2))) return true } return false } }
看到一个面试题,JSON.stringify 是 javascript
的一个方法返回一个json格式的字符串,效果以下
const obj = {a:1, b:2} JSON.stringify(obj) // => '{"a":1,"b":2}'
当要转化的对象有“环”存在时(子节点属性赋值了父节点的引用),为了不死循环,JSON.stringify 会抛出异常,例如:
var a = [1] a.push(a) JSON.stringify(a) // => Uncaught TypeError: Converting circular structure to JSON
写一个函数判断参数是否包含 环
,本身想到的是用 map
对象把是对象的值作为键存储值,而后判断值是否存在来判断是否回环, 要注意每一次要用一个新的 map 对象,避免同级别相互引用判断错误的状况
let isCircular = (o) => { var flag = false const func = (obj, map = new Map()) => { map.set(obj, true) Object.values(obj).forEach(d=> { if (flag) return if (typeof d == 'object') { if (map.get(d)) { flag = true return } else { let newmap = new Map(map) func(d, newmap) } } }) } func(o) return flag }
给一个数字,写一个函数根据数字生成全部形式良好的括号组合 2 => ["()()", "(())"] 3 => [ "((()))", "(()())", "(())()", "()(())", "()()()" ]
想了一下有一个思路,就是根据 ()
里面的包含几个子 ()
来得出全部状况。 好比给出的数字是5, 那么循环到5,第n 就有 ( [func(n)的结果] )
* func(4-n)的结果
。
一直想着以一个优雅的方式处理边界的问题,可是想半天都没结果,只能写的丑陋点了。
var generateParenthesis = function(n) { if(n == 0) return [] if(n == 1) return ['()'] let arr = [] for(let i = 0; i < n; i++) { if( i == 0) { arr = arr.concat(generateParenthesis([n-1]).map(d => '()' + d )) } else if (i == n-1){ arr = arr.concat(generateParenthesis([n-1]).map(d => '(' + d + ')')) } else { generateParenthesis(i).forEach(d => { let eachres = '(' + d +')' generateParenthesis(n- i -1).forEach(c => { arr.push(eachres + c) }) }) } } return arr };