{"id":25350904,"url":"https://github.com/vincevargadev/grind75_dart","last_synced_at":"2025-09-13T05:41:41.521Z","repository":{"id":133199659,"uuid":"517992368","full_name":"vincevargadev/grind75_dart","owner":"vincevargadev","description":"Dart solutions for the Grind 75 coding challenges. LeetCode, Blind 75, Neetcode 150, Grind 169. Data structures and algorithms.","archived":false,"fork":false,"pushed_at":"2022-09-25T13:37:34.000Z","size":159,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-02-14T17:18:55.525Z","etag":null,"topics":["blind75","dart","grind169","grind75","leetcode"],"latest_commit_sha":null,"homepage":"https://www.techinterviewhandbook.org/grind75","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vincevargadev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-07-26T09:16:52.000Z","updated_at":"2025-01-22T14:55:08.000Z","dependencies_parsed_at":null,"dependency_job_id":"0b201889-9d23-4432-972d-bdc538b0c969","html_url":"https://github.com/vincevargadev/grind75_dart","commit_stats":null,"previous_names":["vincevargadev/grind75_dart","dartsidedev/grind75"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vincevargadev%2Fgrind75_dart","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vincevargadev%2Fgrind75_dart/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vincevargadev%2Fgrind75_dart/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vincevargadev%2Fgrind75_dart/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vincevargadev","download_url":"https://codeload.github.com/vincevargadev/grind75_dart/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247934808,"owners_count":21020724,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blind75","dart","grind169","grind75","leetcode"],"created_at":"2025-02-14T17:18:53.835Z","updated_at":"2025-04-08T21:49:12.992Z","avatar_url":"https://github.com/vincevargadev.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Grind 75 in Dart\n\n\u003e All`*` the 169 challenges of the Grind 75 LeetCode study plan solved in beautiful, idiomatic Dart.\n\n`*`: Well, not yet, but I am on it! 🚀\n\nYou can find all the questions and solutions in the [`test`](https://github.com/dartsidedev/grind75/tree/main/test)\nfolder.\n\n## Resources\n\n* [Grind 75](https://www.techinterviewhandbook.org/grind75)\n* [Blind 75](https://leetcode.com/discuss/general-discussion/460599/blind-75-leetcode-questions)\n* [LeetCode](https://leetcode.com/)\n* [Dart](https://dart.dev/)\n    * [Language Tour](https://dart.dev/guides/language/language-tour)\n    * [Effective Dart](https://dart.dev/guides/language/effective-dart)\n\n## Important todos\n\n* All sorting algorithms. What's a good default? What is used by Dart (and other progr. languages)? Faster than nlogn?\n\n## Cheat sheet\n\nHere, I summarize the core ideas, Dart syntax, data structures or algorithms that I keep forgetting.\n\n### Sorting\n\nYou can find the default implementation of `List.sort`\nin [`github.com/dart-lang`'s `sdk/lib/internal/sort.dart`](https://github.com/dart-lang/sdk/blob/main/sdk/lib/internal/sort.dart)\n.\n\nIt's the dual-pivot quicksort algorithm as presented in\n[Vladimir Yaroslavskiy's paper](https://codeblab.com/wp-content/uploads/2009/09/DualPivotQuicksort.pdf).\nIt uses two pivot elements (so partitions to three parts).\n\nThe dual pivot quicksort algorithm reduces the average number of swaps\nby [20%](https://www.reddit.com/r/programming/comments/9jj5z/vladimir_yaroslavskiys_dualpivot_quicksort/).\nThe average number of comparisons stays the same.\n\nOn average, it takes $O(n \\log n)$ comparisons, in the worst case $O(n^2)$.\n\nFor lists with a length less than 32, Dart uses [insertion sort](https://en.wikipedia.org/wiki/Insertion_sort), $O(n^2)\n$.\n\n### Queue\n\nA `Queue` is a collection that can be manipulated at both ends.\n\nIts implementers, `DoubleLinkedQueue` and `ListQueue`, are efficient for queue or stack usage.\n\n```dart\n// Queue, DoubleLinkedQueue, ListQueue\nimport 'dart:collection';\n```\n\nThe `DoubleLinkedQueue` is an implementation of the `Queue` based on a double-linked list.\nIt allows **constant time add, remove-at-ends and peek operations**.\n\n```dart\n\nfinal doubleLinkedQueue = DoubleLinkedQueue\u003cint\u003e();\n```\n\nThe `ListQueue` is a list based `Queue`.\nIt keeps a cyclic buffer of elements, and grows to a larger buffer when it fills up.\nThis guarantees **constant time peek and remove operations, and amortized constant time add operations**.\n\n```dart\n\nfinal initialCapacity = 16; // Default init capacity is 8.\nfinal listQueue = ListQueue\u003cint\u003e(initialCapacity);\n```\n\n| | add (to ends) | remove (at ends) | peek |\n|---|:-:|:-:|:-:|\n| `DoubleLinkedQueue` | $O(1)$ | $O(1)$ | $O(1)$ |\n| `ListQueue`  | amortized $O(1)$ | $O(1)$ | $O(1)$ |\n\n**Minimalist extensions for stacks and queues**.\n\nSometimes, I find that the traditional queue operations come easier, especially if I am under stress and I feel\npressured to be fast and clear while at an interview.\n\nFor this reason, I prefer to add the \"minimalist\" queue and stack static extension methods on the `Queue`.\n\n```dart\nextension MinimalistQueue\u003cE\u003e on Queue\u003cE\u003e {\n  void enqueue(E value) =\u003e addLast(value);\n\n  E dequeue() =\u003e removeFirst(); // throws StateError if empty!\n  E? peek() =\u003e firstOrNull; // For most problems, peek is not needed.\n}\n```\n\n```dart\nextension MinimalistStack\u003cE\u003e on Queue\u003cE\u003e {\n  void push(E value) =\u003e addLast(value);\n\n  E pop() =\u003e removeLast(); // throws StateError if empty!\n  E? peek() =\u003e lastOrNull; // For most problems, peek is not needed.\n}\n```\n\n### Regex\n\n```dart\n// Assumes string's of length 1\nbool get isAlphaNumericChar =\u003e RegExp(r'^[\\w\\d]$').hasMatch(this);\n// or RegExp(r'^[a-zA-Z0-9]$')\n```\n\n### ASCII code units\n\nFor day-to-day work, knowing and remembering the ASCII code units of different characters is completely useless.\n\nHowever, in many coding challenges, it can come in handy.\n\n|           |   starts |      ends | count |\n|-----------|---------:|----------:|------:|\n| numbers   | 48 (`0`) |  57 (`9`) |    10 |\n| uppercase | 65 (`A`) |  90 (`Z`) |    26 |\n| lowercase | 97 (`a`) | 122 (`z`) |    26 |\n\nFor example, if you know that the input is ASCII-only, you can determine very easily\nwhether a character is alphanumeric using code units.\n\n```dart\n// Assumes string's of length 1\nbool get isAlphaNumericChar {\n  final codeUnit = codeUnitAt(0);\n  final isNumber = 48 \u003c= codeUnit \u0026\u0026 codeUnit \u003c= 57;\n  final isUpperCase = 65 \u003c= codeUnit \u0026\u0026 codeUnit \u003c= 90;\n  final isLowerCase = 97 \u003c= codeUnit \u0026\u0026 codeUnit \u003c= 122;\n  return isNumber || isLowerCase || isUpperCase;\n}\n```\n\nIn this example, let's say we know about the input string that it only contains lowercase letters (English alphabet).\nIf we need to store, for example, a counter for each letter in a list, we can write this static extension getter\nto convert from strings to the indices for the list.\n\n```dart\nextension CharToIndex on String {\n  // Assumes only lowercase and length == 1 \n  int get charIndex =\u003e codeUnitAt(0) - 97;\n}\n```\n\n#### Tree traversal\n\n* Preorder: root, left, right\n* Post order: left, right, root\n* Inorder: left, root, right\n\n#### Binary search\n\nYou need to be able to write a binary search in a minute, you don't have 10 minutes to think about edge cases.\n\nTODO: Check card: https://leetcode.com/explore/learn/card/binary-search/\n\n#### Reverse linked list\n\nMust know it well!\n\n### Mix\n\n```dart\nimport 'dart:math';\n\nfinal maxValue = max(a, b);\n// or\nimport 'dart:math' as math;\n\nfinal maxValue = math.max(a, b);\n```\n\n```dart\nimport 'package:collection/collection.dart';\n\n/// Equality on lists.\n///\n/// Two lists are equal if they have the same length and their elements\n/// at each index are equal.\nbool match(List\u003cint\u003e a, List\u003cint\u003e b) =\u003e const ListEquality().equals(a, b);\n```\n\n```dart\n// part of dart core\n\n// Check whether two references are to the same object.\nexternal bool identical(Object? a, Object? b);\n```\n\n```dart\n// A simplified (int only) version of\n// the ListEquality.equals from package:collection\nbool listEquals(List\u003cint\u003e? list1, List\u003cint\u003e? list2) {\n  // Are they identical?\n  if (identical(list1, list2)) return true;\n\n  // Consider nulls\n  if (list1 == null || list2 == null) return false;\n\n  // Check lengths and return early if don't match\n  var length = list1.length;\n  if (length != list2.length) return false;\n\n  // Check every item, if they don't match return\n  for (var i = 0; i \u003c length; i++) {\n    if (list1[i] != list2[i]) return false;\n  }\n\n  // Yay, they are equal!\n  return true;\n}\n```\n\n## Disclaimers\n\n### Coding conventions\n\nI do not always follow the official Dart style guide\nor rules that are in most popular linting libraries enabled.\n\nYou can find below the list of rules that I do not follow with a reason as to why that is.\n\n* `curly_braces_in_flow_control_structures`: I don't want to \"spend\" three lines just to write a simple `while`, `if`\n  , `for`.\n* `avoid_multiple_declarations_per_line`: sometimes two declarations just belong together, and at interviews, you really\n  don't have enough time to declare everything in a new line.\n\n### Test quality\n\nI didn't spend time writing the perfect test description for my tests.\nI made sure that I have enough tests to spot any potential mistakes and that I add the examples from LeetCode.\n\nThis doesn't mean that in your day job, you should write the tests like I did in this repository,\nit just means that I wanted to focus on solving the problem correctly.\n\nUnfortunately, LeetCode doesn't work with Dart, if you want to change that, upvote this issue.\nLeetCode doesn't do it for me for Dart).\n\n### Solution descriptions\n\nThe solution descriptions are mostly for myself. For cases, where the challenge was very easy for me, I didn't spend\nmuch effort on describing the solution.\n\n## Challenges\n\nBelow you can find a list of challenges that I already solved.\n\nFollowing [Neetcode's advice](https://www.youtube.com/watch?v=SVvr3ZjtjI8), I summarize each challenge's core concepts\nand different ways to solve the challenges with its pros and cons.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eTwo Sum\u003c/b\u003e 🏷 \u003ci\u003earray\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/two_sum_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/two-sum/)\n\n\u003e Exactly one solution. You may not use the same element twice.\n\u003e Return indices of the two numbers such that they add up to target.\n\nWe need to return the indices.\nCreate a map where _the key is the number value_ and _the value is its index_.\n\nIterate over numbers: store visited numbers and their indices in the map.\n\nAs you iterate, check whether current number has a _complement_ in the map that adds up to target.\nIf it does, return the indices.\nIf it doesn't, add number to the map.\n\n**Complexity analysis**: $n$ is the number of elements in the list.\n\n* **Time complexity**: $O(n)$, as you might iterate over the whole list.\n* **Space complexity**: $O(n)$, as you might need to store almost all elements and their indices in the map.\n\nOther solutions:\n\n* **Brute force**: double loop, return when the two numbers add up to the target.\n    * **Time complexity**: $O(n^2)$, for each of $n$ elements, we try to find its complement by looping through the rest\n      of the list.\n    * **Space complexity**: $O(1)$, no extra space that depends on the input size is necessary.\n* [Sort list](https://leetcode.com/problems/two-sum-ii-input-array-is-sorted) first, then on a sorted list, find values\n  with two pointers (from start and end).\n    * **Time complexity**: $O(n \\log n)$, because sort $O(n \\log n)$ + two pointers $O(n)$.\n    * **Space complexity**: $O(n)$, sort and two-pointers would be possible with $O(1)$, but we need to store original\n      indices $O(n)$.\n    * This solution, as the list is not already sorted and we need to return the original indices, is fairly\n      complicated, and doesn't perform too well (neither in space nor time complexity).\n\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eValid Parentheses\u003c/b\u003e 🏷 \u003ci\u003estack\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/valid_parentheses_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/valid-parentheses/)\n\n\u003e input string consists of parentheses/brackets only `()[]{}`\n\nPush opening parenthesis/bracket to a stack.\nPop off when closing, and make sure they are matching.\nDon't forget to check at the end if the stack is empty.\nRemember to pop off only if stack is not empty (or use peek).\n\n**Complexity analysis**: $n$ is the length of the input string.\n\n* **Time complexity**: $O(n)$, as you iterate over the whole input string, and potentially adding half of them to a\n  stack. Pushing and popping on a stack can be a $O(1)$ operation if the stack is efficient.\n* **Space complexity**: $O(n)$, we need a stack that might contain $n$ elements.\n\n[Solution variant](https://leetcode.com/problems/valid-parentheses/discuss/500491/Rust-0ms), you could immediately push\nthe closing parenthesis onto the stack, it actually ends up looking pretty nice.\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eMerge Two Sorted Lists\u003c/b\u003e 🏷 \u003ci\u003elinked list\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/merge_two_sorted_lists_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/merge-two-sorted-lists/)\n\n_Trick: pre-head pointer significantly simplifies the iterative algorithm._\n\nWhile both lists are not empty, pick one off the lists and add to the results.\nMove pointer.\nDo not forget to add the remaining items of the longer list to the list.\nReturn the pre-head's next as result.\n\nConsider empty nodes. Do not assume the two lists are of equal length.\n\n**Complexity analysis**, $n$ and $m$ are the lengths of the input linked lists:\n\n* **Time complexity**: $O(n+m)$ (linear with total length), because we simply iterate over both lists and picking the\n  correct.\n* **Space complexity**: $O(1)$, only need a couple of variables, constant space, and the returned list consists of nodes\n  already created before the solution algorithm ran.\n\nAlternative solutions:\n\n* Recursive solution. Basically the same, just with different space complexity due to the stack.\n\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eBest Time to Buy and Sell Stock\u003c/b\u003e 🏷 \u003ci\u003earray\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/best_time_to_buy_and_sell_stock_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/best-time-to-buy-and-sell-stock/)\n\n_Clarify at the interview_:\n\n* What is the input, `int` vs `num` vs `double`? In this case, we work with `int`.\n* Can it be negative/positive? It doesn't affect the algorithm.\n* What should the solution return if it is impossible to achieve any profit? Return 0 if no profit possible.\n\nKeep track of min price \"so far\".\nCurrent profit is price minus the min price so far.\nUpdate max profit if current profit greater.\nHandle negative profit edge case (must return 0).\n\n**Complexity analysis**, $n$ is the length of the list:\n\n* **Time complexity**: $O(n)$, as you iterate over the whole list in a single pass.\n* **Space complexity**: $O(1)$, because you only need two variables holding integers.\n\nAlternative solutions:\n\n* brute force: double loop, calculate profit for each possible pair.\n    * **Time complexity**: $O(n^2)$, for each number, sweep the rest of the list.\n    * **Space complexity**: $O(1)$.\n\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eValid Palindrome\u003c/b\u003e 🏷 \u003ci\u003estring\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/valid_palindrome_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/valid-palindrome/)\n\nStart with two pointers at each end of the string.\nIf a letter is not alphanumeric, move pointer to next alphanumeric.\nMake sure that the left pointer is always to the left of the right pointer.\nWhenever the two pointers contain alphanumeric chars, compare.\nIf the values for the two pointers don't match, return \"not a palindrome\".\n\n**Complexity analysis**, $n$ is the length of the string:\n\n* **Time complexity**: $O(n)$, as we traverse over each character at most once.\n* **Space complexity**: $O(1)$, because you only need two variables holding integers.\n\nAlternative solutions:\n\n**Functional approach**\n\n1. Filter invalid characters and transform to lowercase (`split`+`where`+`map`+`join`).\n2. Check if palindrome\n    * two pointers (now significantly easier to implement), or\n    * reverse the string and compare against the original.\n\n**Complexity analysis**, $n$ is the length of the string:\n\n* **Time complexity**: $O(n)$, as we iterate over the string: filter out non-alphanumeric values, map to lowercase,\n  create string, create reversed, compare. All of these steps run in linear time.\n* **Space complexity**: $O(n)$, for the supporting data structures: split list, joined string, reversed joined.\n\nThe functional approach, compared to the optimal iterative approach, has worse space complexity ($O(n)$ vs. $O(1)$).\nIn practice, it has both a worse memory usage and slower runtime.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eInvert Binary Tree\u003c/b\u003e 🏷 \u003ci\u003ebinary tree\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/invert_binary_tree_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/invert-binary-tree/)\n\n\u003e The inverse of a tree with root $R$, and subtrees $r$ and $l$, is a tree with root $R$, whose\n\u003e right subtree is the inverse of $l$, and whose left subtree is the inverse of $r$.\n\nInvert tree recursively. Swap children, then invert left and right subtrees. Handle null case.\n\nBoth pre-order and post-order traversal give the right answer.\n\n**Complexity analysis**, $n$ is the number of the nodes in the tree:\n\n* **Time complexity**: $O(n)$, we visit each node once.\n* **Space complexity**: $O(n)$, the recursion stack will be as high as the tree, which in the worst case is equal to the\n  number of nodes.\n\nTODO: Solve iteratively, both post and preorder.\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eValid Anagram\u003c/b\u003e 🏷 \u003ci\u003estring\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/valid_anagram_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/valid-anagram/)\n\n\u003e An Anagram is a word or phrase formed by rearranging the letters of a\n\u003e different word or phrase, typically using all the original letters exactly once.\n\nTwo words are anagram if they both contain the same letters, the same number of times.\n\nReturn early if lengths don't match.\nCreate counter (list or map).\nCheck if counts match.\n\n**Complexity analysis**, where $n$ is the length of the strings:\n\n* We assume $n$ is the length of both strings. If the lengths don't match, we can return immediately.\n* **Time complexity**: $O(n)$ as we need to iterate over the strings to create the frequency/counter table.\n* **Space complexity**: $O(1)$, the counter's space requirements stay constant no matter how large $n$ is: The counter\n  will be a fixed length list with length 26.\n  The same is true even for unicode, just the map will be much bigger.\n\nConsider creating a helper class `Counter` that can be created\nfrom a string and then compared against another counter.\n\nThe `Counter` should wrap a fixed-length list for ASCII-only.\n\nIf you are not allowed to use `package:collection`'s `ListEquality`, be prepared to implement it.\n\nFollow up: **unicode**?\nIn Version 14.0 of the Unicode Standard, there are **144K characters**.\nTo fit all possible unicode characters in a list, the list would have to contain 1M+ elements\n(unicode is evolving, 1M+ is the hypothetical max).\nThat's wasteful if the strings are short (and anything less than a million characters counts as short in this case).\n**Change from fixed length list to hash map for storing the counters.**\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eBinary Search\u003c/b\u003e 🏷 \u003ci\u003ebinary search\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/binary_search_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/binary-search/)\n\nLearn to write binary search, it doesn't really get much simpler than that.\nPay attention to empty list, first element, last element. Practice templates.\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eFlood Fill\u003c/b\u003e 🏷 \u003ci\u003egraph\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Iterative Solution in Dart](./test/flood_fill_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/flood-fill/)\n\nDepth-first search, either iteratively or recursively.\n\n**Complexity analysis**, where $n$ is the number of rows and $m$ in the number of columns in the image, and the total\nnumber of pixels is $p = m n$.\n\n* **Time complexity**: $O(n m) = O(p)$ as we might process every pixel.\n* **Space complexity**: $O(n m) = O(p)$ for the stack (either the call stack in the recursive solution or the\n  queue/stack for the iterative solution).\n\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eMaximum Subarray\u003c/b\u003e 🏷 \u003ci\u003edynamic programming\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/maximum_subarray_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/maximum-subarray/)\n\nIterate over the list. Keep track of the \"current\" maximum sum, and the maximum sum \"so far\".\n\nWhen the current single item is better than the current sum plus the current single item,\nreset the current max sum to the current item only. If it isn't better, add to the sum.\n\nThis basically means that if the current sum is negative, you stop using the past values.\n\n```dart\ncurrent = math.max(current + v, v);\n// is the same as:\ncurrent = current.isNegative\n?\nvalue : current + value;\n```\n\nDon't forget to update the maximum value \"so far\" when needed.\n\nPS: This is Kadane's algorithm.\n\n**Complexity analysis**, where $n$ is the length of the list.\n\n* **Time complexity**: $O(n)$ as we need to iterate over all items once.\n* **Space complexity**: $O(1)$ as we only need to use two variables, one for the \"current\" max and the other for the\n  max \"so far\". This space doesn't depend on $n$.\n\nAlternative solutions:\n\n* **Brute force**: Three loops. Two for moving `start` and `end` indices, a third for calculating the sum.\n    * **Time complexity**: $O(n^3)$ for the three nested loops.\n    * **Space complexity**: $O(1)$.\n* **Optimized brute force**: One loop for moving the `start` index. The second loop moves the `end` index while\n  simultaneously updating the `currentMax` value. Compare against `max`.\n    * **Time complexity**: $O(n^2)$ for the two nested loops. The improvement over the $O(n^3$ solution comes from the\n      fact that we recognized that when we add one more item to the sub-list, we don't need to recalculate the current\n      sum completely: $ \\sum_{k = 0}^{n + 1} a_k = a_{n + 1} \\sum_{k = 0}^{n} a_k $.\n    * **Space complexity**: $O(1)$.\n* **Divide and Conquer**: **TODO.**\n    * **Time complexity**: $O(n \\log n)$.\n    * **Space complexity**: $O(\\log n)$.\n\nYou can find out more about this issue\non [Wikipedia - Maximum Subarray Problem](https://en.wikipedia.org/wiki/Maximum_subarray_problem).\n\u003c/details\u003e\n\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eLowest Common Ancestor of a Binary Search Tree\u003c/b\u003e 🏷 \u003ci\u003ebinary search tree\u003c/i\u003e\u003c/summary\u003e\n\n🐌 Can't submit solutions with Dart on LeetCode yet for this problem.\n\n\u003e [Solution](./test/lowest_common_ancestor_of_a_binary_search_tree_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/)\n\n\u003e The lowest common ancestor is defined between two nodes $p$ and $q$ as the lowest node in $T$ tree that has both $p$\n\u003e and $q$ as descendants (where we allow a node to be a descendant of itself).\n\nWe need to realize that in a binary search tree, a node is the lowest common ancestor of\n$p$ and $q$, when one value is on the left side and the other value is on the right side of the node.\n\nWhen both $p$ and $q$ are smaller than current, go to the left,\nwhen both $p$ and $q$ are larger, go to the right.\n\nWhen one is smaller, the other one is larger, the current node is the lowest common ancestor.\nWhen the current value matches one of $p$ or $q$, the current node is the lowest common ancestor.\n\nThe solution can be done iteratively or recursively.\n\n**Complexity analysis**, where $n$ is the number of nodes in the binary search tree, and $h$ is the height of the binary\nsearch tree.\n\n**Iterative solution**:\n\n* **Time complexity**: $O(h)$. In the worst case, $h = n$, and therefore $O(n)$\n  because if the binary search tree is unbalanced (or degenerated to a linked list) and the values are at the bottom,\n  (almost) all nodes in the binary search tree will be visited. In a balanced binary search tree $h = \\log n$.\n  In this case, the time complexity will be $O(\\log n)$.\n* **Space complexity**: $O(1)$, no extra space needed apart from a variable.\n\n**Recursive solution**:\n\n* **Time complexity**: $O(n)$ (really $O(h)$), for balanced $O(\\log n)$.\n* **Space complexity**: $O(n)$ (as in the worst case $h = n$) as we need space for the recursion stack. In case the tree\n  is balanced, $h = \\log n$.\n\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eBalanced Binary Tree\u003c/b\u003e 🏷 \u003ci\u003ebinary tree\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/balanced_binary_tree_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/balanced-binary-tree/)\n\nSolutions. Iterative, recursive.\n\n\u003e a binary tree in which the left and right subtrees of every node differ in height by no more than 1.\n\nGet the height of the left and right subtrees. Use -1 to show that it is not balanced.\n\nTODO: Iterative\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eImplement Queue using Stacks\u003c/b\u003e 🏷 \u003ci\u003estack\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/implement_queue_using_stacks_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/implement-queue-using-stacks/)\n\nHave two stacks, and a phase internally whether we were pushing or popping off the queue.\nWhen changing phases, move all items from one stack to another first, then add or remove.\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eLinked List Cycle\u003c/b\u003e 🏷 \u003ci\u003elinked list\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/linked_list_cycle_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/linked-list-cycle/)\n\nSolutions:\n\n* Iterate over linked list and store seen nodes in a map. If node is already seen, return that it has a cycle. If\n  reaches the end of the list, it has no cycles. TC O(n), SC O(n)\n* Double pointers. Fast and slow pointers. Fast moves two at a time, slow moves one at a time. if they \"meet\", it's a\n  cycle. Careful with the stop condition.\n\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eFirst bad version\u003c/b\u003e 🏷 \u003ci\u003ebinary search\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/first_bad_version_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/first-bad-version/)\n\nLearn to write binary search, it doesn't really get much simpler than that.\nPay attention to empty list, first element, last element. Practice templates.\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eRansom Note\u003c/b\u003e 🏷 \u003ci\u003ehash table\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/ransom_note_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/ransom-note/)\n\nFor letter frequency counter, use map for unicode, use list of length 26 for ASCII lowercase.\n\nSimple solution:\nYou can use two maps/lists as frequency counters, then check whether the magazine's counters are highers for each\nposition than in the ransom note.\n\nAlternatives.\nTerminate early (earlier?): Start with one map for the magazine, then start removing letters based on the ransom note.\nWhenever your magazines hit 0 counts, return false.\nAlternative II. You can also sort and compare, sort and put it into a stack, etc...\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eClimbing Stairs\u003c/b\u003e 🏷 \u003ci\u003edynamic programming\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/climbing_stairs_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/climbing-stairs/)\n\nIt's Fibonacci's twin sister.\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eLongest Palindrome\u003c/b\u003e 🏷 \u003ci\u003estring\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/longest_palindrome_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/longest-palindrome/)\n\nBuild letter counter (frequency).\nKnow your code units: A for 65, Z for 90, a for 97, z for 122.\nAlternatively, use a map.\n\nWe can use letters in pairs to build the palindrome length (use int division by 2).\nThen, if there was an odd letter, we can add it to the middle (counts as +1).\n\u003c/details\u003e\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eReverse Linked List\u003c/b\u003e 🏷 \u003ci\u003elinked list\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/reverse_linked_list_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/reverse-linked-list/)\n\nHelpful: pre-head!\nTODO: check my past solutions, one of them must be intuitive enough to remember and solve in 3 minutes.\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eMajority Element\u003c/b\u003e 🏷 \u003ci\u003earray\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/majority_element_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/majority-element/)\n\nPotential solutions\n\n* Double loop: Count how often the element is in the list, if it's greater than half, it's the solution. TC O(n^2), SC:\n  O(1).\n* Sort, then sweep for greatest. Sort TC O(n log n), SC O(1). Sweep TC O(n), SC O(1). Total: TC O(n log n), SC O(1).\n    * Improvement: once sorted, we don't need to sweep. It's always the middle element.\n* Store counter in map, if majority, return. TC O(n), SC O(n).\n* Random: Pick an index randomly, there is at least a 50% chance it will be the majority item. O(n) to verify. Repeat\n  until found. Worst case scenario: infty.\n\nTODO:\n\n* Boyer-Moore\n* Divide and Conquer\n\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eAdd Binary\u003c/b\u003e 🏷 \u003ci\u003ebinary\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/add_binary_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/add-binary/)\n\nAdd Binary.\n\u003c/details\u003e\n\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eMiddle of the Linked List\u003c/b\u003e 🏷 \u003ci\u003elinked list\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution in Dart (two pointers)](./test/middle_of_the_linked_list_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/middle-of-the-linked-list/)\n\nPotential solutions:\n\n* First pass: count elements. Second pass: go to the middle. TC O(n), SC O(1)\n* One-pass algorithm: two pointers, slow and fast. When fast is at the end, slow is in the middle.\n\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eContains duplicate\u003c/b\u003e 🏷 \u003ci\u003earray\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/contains_duplicate_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/contains-duplicate/)\n\nPotential solutions:\n\n* brute force: double loop. TC O(n^2), SC O(1)\n* sort then look for duplicates. TC O(n log n + n), SC O(1). Mutates input! (or if it doesn't mutate, then it needs a\n  copy O(n))\n* store seen in map, iterate over elements and check if already seen. TC O(n), SC O(n). Does not mutate input.\n\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eRoman to Integer\u003c/b\u003e 🏷 \u003ci\u003emath\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/roman_to_integer_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/roman-to-integer/)\n\nKeep track of value so far.\nIterate over the string.\nCheck if the next two characters make up an exception. If they do: add to value, skip next char.\nIf they don't: treat first char as regular, add to value.\n\nAlternative solutions: [Left to Right](https://www.youtube.com/watch?v=3jdxYj3DD98)\n. [Right to Left](https://www.youtube.com/watch?v=dlATMslQ6Uc).\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eSingle Number\u003c/b\u003e 🏷 \u003ci\u003ebinary\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/single_number_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/single-number/)\n\n\u003e every element appears twice except for one\n\nSolutions:\n\n* Iter over items: if in second array, remove the item, if it isn't, add the item. In the end, only the single number\n  will stay\n* Build map of frequencies. Iterate over map entries, find where value is 1, return key. TC O(n), SC O(n) (this\n  complexity is not accepted according to the answer)\n* \"Bit xor\" `^` all the way. Can reduce or loop.\n* math: 2 * (a1 + a2 + ... + an + b) - (a1 + a1 + ... + an + an + b) = b. Sum up all items in list. Then add all items\n  in a set, sum up, double it. The diff is the number.\n\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eMissing Number\u003c/b\u003e 🏷 \u003ci\u003ebinary\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/missing_number_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/missing-number/)\n\nSolutions:\n\n* Sort TC O(n log n), then find missing TC O(n).\n* Bit xor again! `^`. Xor together all the numbers, then xor with n. The result is the missing number.\n* Calculate expected sum, calculate actual sum, the diff is the missing number\n    * expected sum can be either calculated O(n), or use Gauss formula\n\n\u003c/details\u003e\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003ePalindrome Number\u003c/b\u003e 🏷 \u003ci\u003emath\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/palindrome_number_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/palindrome-number/)\n\nFirst approach: convert to string, then solve it as if was a string.\n\nSecond approach: convert it to a list, then solve it as if it were a list. Use `%` and `~/`.\n\nThird approach: get the last and first digits. Transform the input. Repeat. Return false if they don't match.\n\nFourth approach: create reverted number, then compare integers.\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eSquares of a Sorted Array\u003c/b\u003e 🏷 \u003ci\u003earray\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/squares_of_a_sorted_array_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/squares-of-a-sorted-array/)\n\nMust consider possible negative numbers!\n\nVery brute force solution (does not mutate input): Map square (TC: O(n), SC: O(n)), sort (TC: O(n log n), SC: O(1)).\n\nBrute force solution (mutates input, no extra space at all): Square each number in place (TC: O(n), SC: O(1)), sort the\nlist (TC: O(n log n), SC: O(1)).\n\nTwo-pointer solution: from one of the two ends of the list will come the next biggest square (postive, negative numbers)\n.\nMove two pointers, and the biggest square will be added to a list. You can create a fixed size list beforehand, in this\ncase, the list will be filled from the end (largest) to the start (smallest).\nComplexity: O(n), space O(1) (if we count the output: O(n)).\n\u003c/details\u003e\n\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eK Closest Points to Origin\u003c/b\u003e 🏷 \u003ci\u003eheap\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/k_closest_points_to_origin_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/k-closest-points-to-origin/)\n\n* Helpful math knowledge: do not need sqrt, just use \"x * x + y * y\"\n* Align with interviewer: could the return value be an Iterable?\n\nPossible solutions:\n\n* Total brute force: double loop: when smallest item found, remove it from list, copy into results.\n* Sort list by \"square sums\" TC O(n log n), SC O(1). Copy first k elements into a list TC O(k), SC O(k)\n* Add all elements into a min heap TC O(n), SC O(n). \"Pop off\" the smallest k elements TC O(k log n) (result could be an\n  iterable, not necessarily a list)\n* Add k elements into a max heap. After the kth, every time you add something into the heap, pop off the largest value.\n  At the end, add remaining items to the result (either as list or iterable).\n* TODO: Quick Select\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eBackspace String Compare\u003c/b\u003e 🏷 \u003ci\u003estack\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/backspace_string_compare_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/backspace-string-compare/)\n\n* build two stacks based on inputs: if `#`, pop off the stack. Then, compare the two stacks: check length first, then\n  pop the items of and if there is no match, return false. TC O(n), SC O(n)\n* iterate from the end. If `#`, continue. Char-generator function, for both, get next, compare. TC O(n), SC O(1)\n\n\u003c/details\u003e\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eNumber of 1 Bits\u003c/b\u003e 🏷 \u003ci\u003ebinary\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/number_of_1_bits_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/number-of-1-bits/)\n\nGo over the binary operators and you will be fine.\n\u003c/details\u003e\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eMaximum Depth of Binary Tree\u003c/b\u003e 🏷 \u003ci\u003ebinary tree\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/maximum_depth_of_binary_tree_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/maximum-depth-of-binary-tree/)\n\nRecursive, iterative solutions. Depth = max(left, right) + 1.\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eDiameter of a Binary Tree\u003c/b\u003e 🏷 \u003ci\u003ebinary tree\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/diameter_of_a_binary_tree_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/diameter-of-binary-tree/)\n\nCalculate height for each node: height = max(left, right) + 1.\nCalculate diameter for each node: diameter = leftHeight + rightHeight.\nWhile calculating the heights and diameters, update \"max diameter\".\n\nDo it recursively, and iteratively.\n\nIterative postorder traversal is easy with two stack (though also possible with one), and you keep track of heights in\nmap of nodes to heights.\n\n\u003c/details\u003e\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eCounting bits\u003c/b\u003e 🏷 \u003ci\u003ebinary\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/counting_bits_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/countings-bits/)\n\nSolutions:\n\n* number of bits, n times...\n* TODO: understand and solve all the other solutions\n\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eSame tree\u003c/b\u003e 🏷 \u003ci\u003ebinary tree\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/same_tree_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/same-tree/)\n\nSolutions:\n\n* override ==\n* recursive\n* iterative (use stack)\n\n\u003c/details\u003e\n\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eSubtree of Another Tree\u003c/b\u003e 🏷 \u003ci\u003ebinary tree\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/subtree_of_another_tree_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/subtree-of-another-tree/)\n\nSolutions:\n\n* See same tree for comparing two trees. Traverse the tree and check each node.\n\n\u003c/details\u003e\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eReverse Bits\u003c/b\u003e 🏷 \u003ci\u003ebinary\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/reverse_bits_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/reverse-bits)\n\nGet rightmost bit of the value and add it to the result.\nThen shift the input value to the right and shift the result to the left.\n\nReminder: know your [bitwise operators](https://www.tutorialspoint.com/dart_programming/dart_programming_operators.htm):\nAND, OR, XOR, NOT, left and right shifts.\n\nAccording to [Numbers in Dart](https://dart.dev/guides/language/numbers):\n\n\u003e Depending on the platform, those numeric types (`int` and `double`) have different, hidden implementations.\n\u003e In particular, Dart has two very different types of targets it compiles to:\n\u003e **native** (most often, a 64-bit mobile or desktop processor)\n\u003e and **web** (JavaScript as the primary execution engine).\n\nKeep in mind that on JavaScript, that \"JavaScript converts numbers into 32 bits before the implementation of bitwise\noperators\"\nwhich can lead to [surprising behavior](https://stackoverflow.com/a/73471501/4541492).\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eEvaluate Reverse Polish Notation\u003c/b\u003e 🏷 \u003ci\u003estack\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/evaluate_reverse_polish_notation_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/evaluate-reverse-polish-notation/)\n\nIterate over input.\nIf it's a number, add to stack.\nIf it's an operation, perform operation on top 2 items in the stack, and push result back to stack.\n\n**Complexity analysis**.\n$n$ is the length of the input list.\n**Time complexity**: $O(n)$, as you iterate over the whole list in a single pass. Pushing to and popping off the stack\nis $O(1)$.\n**Space complexity**: $O(n)$, as the supporting stack can never be more than half the length of the input.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eSort Colors\u003c/b\u003e 🏷 \u003ci\u003earray\u003c/i\u003e\u003c/summary\u003e\n\n\u003e [Solution](./test/sort_colors_test.dart)\n\u003e [LeetCode](https://leetcode.com/problems/sort-colors/)\n\nIf we could use Dart's built-in sorting algorithm, it's a one-liner: dual pivot quicksort $O(n \\log n)$ average case,\n$O(n^2)$ worst case.\n\nWe know that the possible values can only be 0, 1, 2, therefore,\nwe can use [counting sort](https://en.wikipedia.org/wiki/Counting_sort).\n\n**Complexity analysis**.\n$n$ is the length of the input list.\n**Time complexity**: $O(n)$, as you iterate over the whole list first to count, then to overwrite.\n**Space complexity**: $O(1)$, as we only need three supporting counter variables.\n\nTODO: There is another one-pass solution I didn't check. Dutch flag.\n\u003c/details\u003e\n\n## Misc\n\n### Save your completed questions\n\n```js\nconsole.log(JSON.stringify(JSON.parse(localStorage.getItem('1:completedQuestions')), null, 2));\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvincevargadev%2Fgrind75_dart","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvincevargadev%2Fgrind75_dart","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvincevargadev%2Fgrind75_dart/lists"}