|
1 | 1 | {
|
2 | 2 | "cells": [
|
| 3 | + { |
| 4 | + "cell_type": "markdown", |
| 5 | + "id": "8160c7a8", |
| 6 | + "metadata": {}, |
| 7 | + "source": [ |
| 8 | + "# Easy" |
| 9 | + ] |
| 10 | + }, |
3 | 11 | {
|
4 | 12 | "cell_type": "markdown",
|
5 | 13 | "id": "cd94da5c",
|
|
270 | 278 | ]
|
271 | 279 | },
|
272 | 280 | {
|
273 |
| - "cell_type": "code", |
274 |
| - "execution_count": null, |
275 |
| - "id": "a4466c1d", |
| 281 | + "cell_type": "markdown", |
| 282 | + "id": "4c463d86", |
276 | 283 | "metadata": {},
|
277 |
| - "outputs": [], |
278 |
| - "source": [] |
| 284 | + "source": [ |
| 285 | + "# Medium" |
| 286 | + ] |
279 | 287 | },
|
280 | 288 | {
|
281 |
| - "cell_type": "code", |
282 |
| - "execution_count": null, |
283 |
| - "id": "0ce3de02", |
| 289 | + "cell_type": "markdown", |
| 290 | + "id": "84914655", |
284 | 291 | "metadata": {},
|
285 |
| - "outputs": [], |
286 |
| - "source": [] |
| 292 | + "source": [ |
| 293 | + "## K Closest Points to Origin\n", |
| 294 | + "\n", |
| 295 | + "* https://leetcode.com/problems/k-closest-points-to-origin/description/\n", |
| 296 | + "***\n", |
| 297 | + "* Time Complexity: O(nlogk)\n", |
| 298 | + " - there are 2 parts to this:\n", |
| 299 | + " 1. we create a Max Priority Queue and add the first k elements to it\n", |
| 300 | + " - for the rest of the points, we compare it with the root. if the value is less than the root, we pop the root and enqueue the new coordinate\n", |
| 301 | + " 2. we then return all k values of the minHeap as the answer\n", |
| 302 | + " - the first step will be the dominant term, O(nlogk)\n", |
| 303 | + " * reason being, we have to check all n points in the points array and if we have to enqueue/dequeue, that process will be O(logk) b/c there are only k elements in the Max PQ\n", |
| 304 | + " - the second step will just be O(k) which is dropped\n", |
| 305 | + "* Space Complexity: O(k)\n", |
| 306 | + " - we create a Max Priority Queue of size k and we dequeue any values if we are adding more to it\n", |
| 307 | + "***\n", |
| 308 | + "* the reason why we use a Max PQ is b/c it is very easy to compare and drop the max value\n", |
| 309 | + " - if we encounter a coordinate smaller than the max, we can drop the max and add that coordinate PQ\n", |
| 310 | + " - when we do this, the next max will bubble up\n", |
| 311 | + " - in addition, we also do not add any values to the Max PQ greater than the max value if we already have k coordinates in it\n", |
| 312 | + " - these 2 things ensure that max values are weeded out and that no other max values can be added in\n", |
| 313 | + " - and if we maintain a PQ of size k, can we just return all the values in it as the answer without doing anything special to get it" |
| 314 | + ] |
287 | 315 | },
|
288 | 316 | {
|
289 | 317 | "cell_type": "code",
|
290 | 318 | "execution_count": null,
|
291 | 319 | "id": "f92bb982",
|
292 | 320 | "metadata": {},
|
293 | 321 | "outputs": [],
|
294 |
| - "source": [] |
| 322 | + "source": [ |
| 323 | + "/**\n", |
| 324 | + " * @param {number[][]} points\n", |
| 325 | + " * @param {number} k\n", |
| 326 | + " * @return {number[][]}\n", |
| 327 | + " */\n", |
| 328 | + "\n", |
| 329 | + "function getParentIndex(index) {\n", |
| 330 | + " return Math.floor((index - 1) / 2);\n", |
| 331 | + "}\n", |
| 332 | + "\n", |
| 333 | + "function getLeftChildIndex(index) {\n", |
| 334 | + " return (index * 2) + 1;\n", |
| 335 | + "}\n", |
| 336 | + "\n", |
| 337 | + "function getRightChildIndex(index) {\n", |
| 338 | + " return (index * 2) + 2;\n", |
| 339 | + "}\n", |
| 340 | + "\n", |
| 341 | + "function hasLeftChild(array, index) {\n", |
| 342 | + " return getLeftChildIndex(index) < array.length;\n", |
| 343 | + "}\n", |
| 344 | + "\n", |
| 345 | + "function hasRightChild(array, index) {\n", |
| 346 | + " return getRightChildIndex(index) < array.length;\n", |
| 347 | + "}\n", |
| 348 | + "\n", |
| 349 | + "function swap(array, index1, index2) {\n", |
| 350 | + " const value = array[index1];\n", |
| 351 | + " array[index1] = array[index2];\n", |
| 352 | + " array[index2] = value;\n", |
| 353 | + "}\n", |
| 354 | + "\n", |
| 355 | + "function heapifyUp(array, compare) {\n", |
| 356 | + " let currentIndex = array.length - 1;\n", |
| 357 | + "\n", |
| 358 | + " while (currentIndex > 0) {\n", |
| 359 | + " let parentIndex = getParentIndex(currentIndex);\n", |
| 360 | + " if (compare(array[parentIndex], array[currentIndex]) > 0) {\n", |
| 361 | + " swap(array, parentIndex, currentIndex);\n", |
| 362 | + " currentIndex = parentIndex;\n", |
| 363 | + " } else {\n", |
| 364 | + " break;\n", |
| 365 | + " }\n", |
| 366 | + " }\n", |
| 367 | + "}\n", |
| 368 | + "\n", |
| 369 | + "function heapifyDown(array, compare) {\n", |
| 370 | + " let currentIndex = 0;\n", |
| 371 | + " while (hasLeftChild(array, currentIndex)) {\n", |
| 372 | + " let smallerChildIndex = getLeftChildIndex(currentIndex);\n", |
| 373 | + "\n", |
| 374 | + " if (hasRightChild(array, currentIndex)) {\n", |
| 375 | + " let rightChildIndex = getRightChildIndex(currentIndex);\n", |
| 376 | + " if (compare(array[smallerChildIndex], array[rightChildIndex]) > 0) {\n", |
| 377 | + " smallerChildIndex = rightChildIndex;\n", |
| 378 | + " }\n", |
| 379 | + " }\n", |
| 380 | + "\n", |
| 381 | + " if (compare(array[currentIndex], array[smallerChildIndex]) > 0) {\n", |
| 382 | + " swap(array, currentIndex, smallerChildIndex);\n", |
| 383 | + " currentIndex = smallerChildIndex;\n", |
| 384 | + " } else {\n", |
| 385 | + " break;\n", |
| 386 | + " }\n", |
| 387 | + " }\n", |
| 388 | + "\n", |
| 389 | + "}\n", |
| 390 | + "const array = Symbol(\"array\");\n", |
| 391 | + "const compare = Symbol(\"compare\");\n", |
| 392 | + "\n", |
| 393 | + "class BinaryHeap {\n", |
| 394 | + " constructor(comparator = (a, b) => a - b) {\n", |
| 395 | + " this[array] = [];\n", |
| 396 | + " this[compare] = comparator;\n", |
| 397 | + " }\n", |
| 398 | + " \n", |
| 399 | + " add(data) {\n", |
| 400 | + " this[array].push(data);\n", |
| 401 | + " heapifyUp(this[array], this[compare]);\n", |
| 402 | + " }\n", |
| 403 | + "\n", |
| 404 | + " isEmpty() {\n", |
| 405 | + " return this[array].length === 0;\n", |
| 406 | + " }\n", |
| 407 | + "\n", |
| 408 | + " peek() {\n", |
| 409 | + " if (this.isEmpty()) {\n", |
| 410 | + " throw new Error(\"Heap is empty.\");\n", |
| 411 | + " }\n", |
| 412 | + "\n", |
| 413 | + " return this[array][0];\n", |
| 414 | + " }\n", |
| 415 | + " \n", |
| 416 | + " poll() {\n", |
| 417 | + " if (this.isEmpty()) {\n", |
| 418 | + " throw new Error(\"Heap is empty.\");\n", |
| 419 | + " }\n", |
| 420 | + "\n", |
| 421 | + " if (this[array].length > 1) {\n", |
| 422 | + " const topValue = this[array][0];\n", |
| 423 | + "\n", |
| 424 | + " const replacementValue = this[array].pop();\n", |
| 425 | + " this[array][0] = replacementValue;\n", |
| 426 | + " heapifyDown(this[array], this[compare]);\n", |
| 427 | + "\n", |
| 428 | + " return topValue;\n", |
| 429 | + " } else {\n", |
| 430 | + " return this[array].pop();\n", |
| 431 | + " }\n", |
| 432 | + " \n", |
| 433 | + " }\n", |
| 434 | + " \n", |
| 435 | + " get size() {\n", |
| 436 | + " return this[array].length;\n", |
| 437 | + " }\n", |
| 438 | + "\n", |
| 439 | + " includes(value) {\n", |
| 440 | + " return this[array].includes(value);\n", |
| 441 | + " }\n", |
| 442 | + "\n", |
| 443 | + " clear() {\n", |
| 444 | + " this[array] = [];\n", |
| 445 | + " }\n", |
| 446 | + "\n", |
| 447 | + " [Symbol.iterator]() {\n", |
| 448 | + " return this.values();\n", |
| 449 | + " }\n", |
| 450 | + "\n", |
| 451 | + " values() {\n", |
| 452 | + " return this[array].values();\n", |
| 453 | + " }\n", |
| 454 | + " \n", |
| 455 | + " toString(){\n", |
| 456 | + " return [...this[array]].toString();\n", |
| 457 | + " }\n", |
| 458 | + "}\n", |
| 459 | + "\n", |
| 460 | + "\n", |
| 461 | + " var euDist = (coords) => {\n", |
| 462 | + " const [x, y] = coords;\n", |
| 463 | + " const powX = Math.pow(0 - x, 2);\n", |
| 464 | + " const powY = Math.pow(0 - y, 2);\n", |
| 465 | + " return Math.sqrt(powX + powY);\n", |
| 466 | + " }\n", |
| 467 | + "\n", |
| 468 | + "var kClosest = function(points, k) {\n", |
| 469 | + " const minHeap = new BinaryHeap((a, b) => euDist(b) - euDist(a))\n", |
| 470 | + " for (let point of points) {\n", |
| 471 | + " if (minHeap.size < k) {\n", |
| 472 | + " minHeap.add(point);\n", |
| 473 | + " }\n", |
| 474 | + " else if (euDist(point) < euDist(minHeap.peek())) {\n", |
| 475 | + " minHeap.poll();\n", |
| 476 | + " minHeap.add(point);\n", |
| 477 | + " }\n", |
| 478 | + " }\n", |
| 479 | + "\n", |
| 480 | + " return [...minHeap];\n", |
| 481 | + "};" |
| 482 | + ] |
| 483 | + }, |
| 484 | + { |
| 485 | + "cell_type": "markdown", |
| 486 | + "id": "6e24ee3d", |
| 487 | + "metadata": {}, |
| 488 | + "source": [ |
| 489 | + "## Task Scheduler" |
| 490 | + ] |
295 | 491 | },
|
296 | 492 | {
|
297 | 493 | "cell_type": "code",
|
298 | 494 | "execution_count": null,
|
299 |
| - "id": "35a1e745", |
| 495 | + "id": "8c45c87d", |
300 | 496 | "metadata": {},
|
301 | 497 | "outputs": [],
|
302 | 498 | "source": []
|
|
0 commit comments