1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
| 20.有效的括号 用栈来做: 1.新建一个栈 2.扫描字符串,遇左括号入栈,遇到和栈顶的左括号匹配的右括号就出栈,类型不匹配就直接判定不合法 ([}) 3.最后判断栈是否为空,不为空也判定不合法 if(s.length%2!==0){return false} const stack = [] for(let i= 0 ;i<s.length;i++}{ const c = s[i] if(c==='('||c==='['||c==='{')){ stack.push(c) }else{ const top = stack[stack.length-1] if(top==='('&&c===')')|| (top==='{'&&c==='}')|| (top==='['&&c===']'){ stack.pop() }else{ return false } } } return stack.length===0
用字典来做: if(s.length%2!==0){return false} const stack = [] const map = new Map map.set('(',')') map.set('[',']') map.set('{','}') for(let i= 0 ;i<s.length;i++}{ const c = s[i] if(map.has(c)){ stack.push(c) }else{ const top = stack[stack.length-1] if(map.get(top)===c){ stack.pop() }else{ return false } } }
933.最近的请求次数(队列先进先出) 有新请求就入队,3000ms前发出的请求出队。 队列的长度就是最近请求次数。 在构造函数内将队列挂载this上 输入:inputs = [[],[1],[100],[3001],[3002]] 输出:[null,1,2,3,3] var RecentCounter = function(){ this.q = [] } RecentCount.prototype.ping = function(t){ this.q.push(t); while(this.q[0]<t-3000){ 时间复杂度,空间复杂度都是O(n) 队头是1 this.q.shift() } return this.q.length; }
237.删除链表中的节点 1、将被删节点的值改为下个节点的值。node.val = node.next.val 5->1->4->9->8 => 5->1->9->9->8 2、删除下个节点。 node.next = node.next.next
206.反转链表 1、反转两个节点只需要把n+1个节点的next指针指向n 2、反转多个节点:双指针遍历链表,重复上述操作 输入:1->2->3->4->NULL 输出:4->3->2->1->NULL 双指针一前一后遍历链表 反转双指针 let p1=head; let p2=NULL; while(p1){ const temp = p1.next p1.next = p2 p2=p1 p1=temp } return p2 2.两数相加 (遍历链表) var addCounts = function(l1,l2){ const l3 = new ListNode(0) let p1 = l1 let p2 = l2 let p3 = l3 let carry=0 while(p1||p2){ const v1 = p1?p1.val:0 const v2 = p2?p2.val:0 const v3 = v1+v2+carry carry = Math.floor(v3/10) p3.next = new List(v3%10) if(p1) p1=p1.next if(p2) p2=p2.next p3=p3.next } if(carry){ p3.next = new ListNode(carry) } return l3.next } 83.删除排序链表中的重复元素 var deleteDuplicates = function(head){ let p = head while(p&&p.next){ if(p.val===p.next.val){ p.next = p.next.next }else{ p=p.next } } return head }
141.环形链表 var hasCycle = function(head){ let slow = head let fast = head while(slow&&fast&&fast.next){ slow =slow.next fast = fast.next.next if(slow === fast){ return true } } return false }
349.两个数组的交集 用集合来做: 解题思路:求交集且无序唯一。nums1=[1,1,2,1],nums2=[2,2] 输出[2] const set1 = new Set(nums1) const set2 = new Set(nums2) return [...set1].filter(item=>nums2.includes(item))
用字典来做: const map = new Map() nums1.forEach(n=>{ map.set(n,true) }) const res = [] nums2.forEach(n=>{ if(map.get(n)){ res.push(n) map.delete(n) } }) return res
1.两数之和 const map = new Map() for(let i=0;i<nums.length;i++){ const n = nums[i] const n2 = target-n if(map.has(n2)){ return [map.get(n2),i] }else{ map.set(n,i) } }
3.无重复字符的最长子串 1、先找出所有的不包含重复字符的子串。 2、找出长度最大那个子串,返回其长度即可。 用双指针维护一个滑动窗口,用来剪切子串。 不断移动右指针,遇到重复字符,就把左指针移动到重复字符的下一位。 过程中,记录所有窗口的长度,并返回最大值0 const l = 0 res = [] const map = new Map for(let r= 0,r<s.length,r++){ if(map.has(s[r])&&map.get(s[r]>=l)){ l=map.get(s[r])+1 } res=Math.max(res,r-l+1) map.set(s[r],r) } return res
时间复杂度为O(n),空间复杂度为O(m),m为字符串中不重复的字符
76、最小覆盖子串 先找出所有的包含T的子串。 找出长度最小那个子串,返回即可。 用双指针维护一个滑动窗口。 移动右指针,找到包含T的子串,移动左指针,尽量减少包含T的子串的长度。 循环找到最小子串 let l = 0 let r = 0 const need = new Map() for(let c of t){ need.set(c,need.has(c)?need.get(c)+1:1) } let res= '' let needType=need.size while(r<s.length){ c1 = s[r] if(need.has(c1)){ need.set(c1,need.get(c1)-1) if(need.get(c1)===0) needType-=1 } while(needType===0){ const newStr = s.substring(l,r+1) if(!res||newStr.length<res.length) res = newStr c2=s[l] if(need.has(c2)){ need.set(c2,need.get(c2)+1) if(need.get(c2)===1) needType+=1 } l+=1
} r+=1 } return res
104.二叉树的最大深度 解题思路 1、最大深度,考虑使用深度优先遍历。 2、深度优先遍历过程中,记录每个节点所在的层级,找出最大的层级即可。 1.一个变量,记录最大深度。 2.优先遍历整棵树,并记录每个节点的层级,同时不断刷新最大深度这个变量。 3.遍历结束返回最大深度这个变量 先验证深度优先遍历的结果有没有问题 var maxDepth = function(root){ let res = 0 const dfs = (n)=>{ if(!n){return;} log(n.val) dfs(n.left) dfs(n.right) } dfs(root) } ------- var maxDepth = function(root){ let res = 0 const dfs = (n,l)=>{ if(!n){return;} log(n.val,l)=>替换res = Math.max(res,l); dfs(n.left,l+1) dfs(n.right,l+1) } dfs(root,1) return res } 这样执行用时很高这是因为它每次都去遍历每个节点的时候都去刷新res 没必要刷新,只要是叶子节点再去刷新就可以了 if(!n.left&&!n.right){ res = Math.max(res,l) }
111.二叉树的最小深度 1、求最小深度,考虑使用广度优先遍历。 2、在广度优先遍历过程中,遇到叶子节点,停止遍历,返回节点层级。 1.广度优先遍历整棵树,并记录每个节点的层级。 2.遇到叶子节点,返回节点层级,停止遍历。 var minDepth = function(root){ if(!root){return;} const q = [root] while(q.length){ const n = q.shift() log(n.val) if(n.left) q.push(n.left) if(n.right) q.push(n.right) } } -------------- var minDepth = function(root){ if(!root){return;} const q = [[root,1]] while(q.length){ const [n,l] = q.shift() log(n.val,l)=> if(!n.left&&!n.right){ return l } if(n.left) q.push([n.left,l+1] if(n.right) q.push([n.right,l+1]) } } 102.二叉树的层序遍历 1、层序遍历顺序就是广度优先遍历。 2、不过在遍历时候需要记录当前节点所处的层级,方便将其添加到不同的数组中。 if(!root)return [] const q = [[root,0]] const res = [] while(q.length){ const [n,l] = q.shift() log(n,val)=> if(!res[l]){ res.push([n.val]) }else{ res[l].push(n.val) } if(n.left) q.push([n,left,l+1]) if(n.right) q.push([n.right,l+1]) } return res
-------------------------- if(!root)return [] const q = [root] const res = [] while(q.length){ let len =q.length res.push([]) while(len--){ const n = q.shift() res[res.length-1].push(n.val) if(n.left) q.push(n.left) if(n.right) q.push(n.right) } } return res
112 路径之和 215.数组中第K个最大元素(最小堆) var findKthLargest = function(nums, k) { const h = new MinHead() nums.forEach(n=>{ h.insert(n) if(h.size()>k){ h.pop() } }) return h.peek() }; 347.前K个高频元素
|