From 58e76dca0c68425c714830f700f66f996ea64377 Mon Sep 17 00:00:00 2001
From: Kolade Chris <65571316+Ksound22@users.noreply.github.com>
Date: Tue, 3 Mar 2026 22:56:05 +0100
Subject: [PATCH] feat(curriculum): add dsa lessons to js v9 cert (#66008)
Co-authored-by: majestic-owl448 <26656284+majestic-owl448@users.noreply.github.com>
---
client/i18n/locales/english/intro.json | 6 +
.../699bf504558ca3acf83b4732.md | 253 ++++++++++++++++++
.../699bf563af9132c9e3807638.md | 236 ++++++++++++++++
.../699bf563af9132c9e3807639.md | 240 +++++++++++++++++
.../699bf563af9132c9e380763a.md | 194 ++++++++++++++
.../699bf563af9132c9e380763b.md | 230 ++++++++++++++++
...orking-with-common-data-structures-js.json | 30 +++
.../structure/superblocks/javascript-v9.json | 6 +-
8 files changed, 1194 insertions(+), 1 deletion(-)
create mode 100644 curriculum/challenges/english/blocks/lecture-working-with-common-data-structures-js/699bf504558ca3acf83b4732.md
create mode 100644 curriculum/challenges/english/blocks/lecture-working-with-common-data-structures-js/699bf563af9132c9e3807638.md
create mode 100644 curriculum/challenges/english/blocks/lecture-working-with-common-data-structures-js/699bf563af9132c9e3807639.md
create mode 100644 curriculum/challenges/english/blocks/lecture-working-with-common-data-structures-js/699bf563af9132c9e380763a.md
create mode 100644 curriculum/challenges/english/blocks/lecture-working-with-common-data-structures-js/699bf563af9132c9e380763b.md
create mode 100644 curriculum/structure/blocks/lecture-working-with-common-data-structures-js.json
diff --git a/client/i18n/locales/english/intro.json b/client/i18n/locales/english/intro.json
index 611a4b89c2b..91df227d554 100644
--- a/client/i18n/locales/english/intro.json
+++ b/client/i18n/locales/english/intro.json
@@ -3286,6 +3286,12 @@
"title": "Recursion Quiz",
"intro": ["Test your knowledge of Recursion with this quiz."]
},
+ "lecture-working-with-common-data-structures-js": {
+ "title": "Working with Common Data Structures",
+ "intro": [
+ "Learn about common data structures and how to work with them in JavaScript."
+ ]
+ },
"lecture-introduction-to-common-searching-and-sorting-algorithms": {
"title": "Introduction to Common Searching and Sorting Algorithms",
"intro": [
diff --git a/curriculum/challenges/english/blocks/lecture-working-with-common-data-structures-js/699bf504558ca3acf83b4732.md b/curriculum/challenges/english/blocks/lecture-working-with-common-data-structures-js/699bf504558ca3acf83b4732.md
new file mode 100644
index 00000000000..412ad05c181
--- /dev/null
+++ b/curriculum/challenges/english/blocks/lecture-working-with-common-data-structures-js/699bf504558ca3acf83b4732.md
@@ -0,0 +1,253 @@
+---
+id: 699bf504558ca3acf83b4732
+title: What Is an Algorithm and How Does Big O Notation Work?
+challengeType: 19
+dashedName: what-is-an-algorithm-and-how-does-big-o-notation-work
+---
+
+# --description--
+
+Every computer program that runs on your device has a specific set of instructions, which are executed in a specific order to complete a task.
+
+The task could be sorting a set of numbers, modifying an image, tracking inventory, or even running your favorite video game.
+
+This is where algorithms come into play. An **algorithm** is a set of unambiguous instructions for solving a problem or carrying out a task.
+
+You can think of algorithms as "recipes". When you cook, recipes list all the ingredients that you'll need, and provide step by step instructions on how to prepare a dish.
+
+Equivalently, you can think of algorithms as "recipes" that tell computers exactly what should be done and how to do it.
+
+Algorithms have two key characteristics:
+
+* They cannot continue indefinitely. They must finish in a finite number of steps.
+
+* Each step must be precise and unambiguous.
+
+
+They may have zero, one, or more inputs, and generate one or more outputs.
+
+The steps of an algorithm are independent from any programming language.
+
+But to actually make them run on a computer, you need to implement them in a programming language, like Python or JavaScript.
+
+If an algorithm is correct, the output for any valid input should match the expected output.
+
+In addition to being correct, algorithms should also be efficient.
+
+Algorithm efficiency can be measured in terms of how long they take to run and how much space they require in memory to complete the task.
+
+Knowing an algorithm's efficiency is very important because it gives you an idea of how well it will perform as the input size grows.
+
+For example, sorting 15 integers is not the same as sorting 1 million integers.
+
+As the process grows in size and complexity, if the algorithm is not efficient enough to handle it, you might end up with a very slow computer program that may even crash the entire system.
+
+That's why it's very important to develop and choose the most efficient algorithms possible.
+
+This is where Big O notation becomes very important.
+
+Big O notation describes the worst-case performance, or growth rate, of an algorithm as the input size increases.
+
+The growth rate of an algorithm refers to how the resources it requires increase as the input size grows.
+
+Big O notation focuses on the worst-case performance because this case is very important to understand how efficient the algorithm can be, even in the worst case scenario, regardless of the input.
+
+Going back to our sorting example, sorting 1 million integers should intuitively take more time and resources than sorting 15 integers.
+
+But how much more?
+
+This really depends on the algorithm that you choose to sort them.
+
+Big O notation will not give you an exact number to describe the algorithm's efficiency, but it will give you an idea of how it scales as the input size grows, based on the number of operations performed by the algorithm.
+
+In Big O notation, we usually denote input size with the letter `n`. For example, if the input is a list, `n` would denote the number of elements in that list.
+
+Constant factors and lower-order terms are not taken into account to find the time complexity of an algorithm based on the number of operations. That's because as the size of `n` grows, the impact of these smaller terms in the total number of operations performed will become smaller and smaller.
+
+The term that will dominate the overall behavior of the algorithm will be the highest order term with `n`, the input size.
+
+For example, if an algorithm performs `7n + 20` operations to be completed, the impact of the constant `20` on the final result will be smaller and smaller as `n` grows. The term `7n` will tend to dominate and this will define the overall behavior and efficiency of the algorithm.
+
+Another example would be an algorithm that takes `20n² + 15n + 7` operations to be completed. The term `20n²` will tend to dominate as `n` grows, so this algorithm would have a quadratic time complexity because the dominant term has `n²`.
+
+Quadratic time complexity is one of many different types of time complexities that you can find in the world of algorithms.
+
+Let's learn about some of the most common ones.
+
+**`O(1)`** is known as "Constant Time Complexity". When an algorithm has constant time complexity, it takes the same amount of time to run, regardless of input size.
+
+For example, checking if a number is even or odd will always take the same amount of time, regardless of the number itself.
+
+```js
+function checkEvenOrOdd(number) {
+ if (number % 2 === 0) {
+ return "Even";
+ } else {
+ return "Odd";
+ }
+}
+```
+
+**`O(log n)`** is known as "Logarithmic Time Complexity". This means that the time required by the algorithm increases slowly as the input size grows. This is common in problems in which the size of the problem is repeatedly reduced by a constant fraction.
+
+For example, a popular search algorithm called Binary Search has `O(log n)` worst-case time complexity. This is because it eliminates half of the remaining elements in each comparison, which makes it more efficient overall.
+
+**`O(n)`** is known as "Linear Time Complexity". The running time of algorithms with this time complexity increases proportionally to the input size.
+
+For example, a `for` loop that iterates over all the elements of a list will perform more iterations as the number of list elements increases. If the list is doubled in size, the number of operations will approximately double as well.
+
+```js
+for (const grade of grades) { // grades is an array
+ console.log(grade);
+}
+```
+
+**`O(n log n)`** is known as "Log-Linear Time Complexity". This is a common time complexity of efficient sorting algorithms, like Merge Sort and Quick Sort.
+
+**`O(n²)`** is known as "Quadratic Time Complexity". The running time of these algorithms increases quadratically relative to the input size, which is generally not efficient for real-world problems.
+
+Nested loops are a common example of quadratic time complexity. The inner loop will perform `n` iterations for each one of the `n` iterations of the outer loop, resulting in `n` squared iterations.
+
+```js
+for (let i = 0; i < n; i++) {
+ for (let j = 0; j < n; j++) {
+ console.log("Hello, World!");
+ }
+}
+```
+
+Other time complexities include "Exponential Time Complexity", denoted as `O(2^n)`, and "Factorial Time Complexity", denoted as `O(n!)`. Both are inefficient for real-world scenarios.
+
+In this graph, you can compare the growth of the mathematical functions that represent the most common time complexities. Think of the x-axis (horizontal) as the input size and the y-axis (vertical) as the running time of the algorithm.
+
+You can see that the Quadratic Time Complexity (`O(n²)`) (yellow) grows much faster than the other ones, while the Constant Time Complexity (`O(1)`) (red) stays constant, even if the input gets larger.
+
+
+
+Great. So far, you've learned about Big O notation in terms of time requirements, but this notation can also be applied to the context of space requirements.
+
+In this context, it describes how the memory space required by the algorithm grows as the input size grows.
+
+Algorithms with "Constant Space Complexity" `O(1)` always require a constant amount of memory space, even as the input gets larger.
+
+An example would be an algorithm that only creates and stores a few variables in memory.
+
+In contrast, the space required by algorithms with "Linear Space Complexity" `O(n)` increases proportionally as the input size grows.
+
+An example of this would be an algorithm that creates and stores a copy of a list of length `n`.
+
+And finally, the space requirements of an algorithm with "Quadratic Space Complexity" `O(n²)` increase quadratically as the input size grows.
+
+An example of this would be creating a 2D matrix, where the dimensions are determined by the input size, storing all possible pairs.
+
+Algorithms are the building-blocks of computer programs, while Big O notation is a powerful framework for analyzing how efficient they are, based on how their time and space requirements in the worst-case scenario scale as the input size grows. Understanding their efficiency is very important for developing software that works efficiently in real-world scenarios.
+
+# --questions--
+
+## --text--
+
+Which of the following best describes an algorithm?
+
+## --answers--
+
+A specific programming language used to write code.
+
+### --feedback--
+
+Think about what you follow when you're trying to achieve a specific task.
+
+---
+
+A set of step-by-step instructions designed to solve a problem or perform a task.
+
+---
+
+A type of computer hardware component.
+
+### --feedback--
+
+Think about what you follow when you're trying to achieve a specific task.
+
+---
+
+A software application used for developing and playing games.
+
+### --feedback--
+
+Think about what you follow when you're trying to achieve a specific task.
+
+## --video-solution--
+
+2
+
+## --text--
+
+What is the primary purpose of Big O notation in the context of algorithms?
+
+## --answers--
+
+To measure the exact time an algorithm takes to run on a specific computer in seconds.
+
+### --feedback--
+
+Think about what Big O notation helps you understand an algorithm's performance when the amount of data it processes gets very large.
+
+---
+
+To count the total number of lines of code in an algorithm.
+
+### --feedback--
+
+Think about what Big O notation helps you understand an algorithm's performance when the amount of data it processes gets very large.
+
+---
+
+To describe how the resource usage of an algorithm grows as the input size increases.
+
+---
+
+To determine the best-case performance of an algorithm.
+
+### --feedback--
+
+Think about what Big O notation helps you understand an algorithm's performance when the amount of data it processes gets very large.
+
+## --video-solution--
+
+3
+
+## --text--
+
+If an algorithm has a time complexity of `O(n)`, what does this mean about its performance?
+
+## --answers--
+
+The algorithm's running time increases proportionally with the input size.
+
+---
+
+The algorithm's running time remains constant regardless of the input size.
+
+### --feedback--
+
+Think about what "linear" means in terms of a direct relationship or a straight line on a graph.
+
+---
+
+The algorithm's running time grows exponentially with the input size.
+
+### --feedback--
+
+Think about what "linear" means in terms of a direct relationship or a straight line on a graph.
+
+---
+
+The algorithm's running time decreases as the input size gets larger.
+
+### --feedback--
+
+Think about what "linear" means in terms of a direct relationship or a straight line on a graph.
+
+## --video-solution--
+
+1
diff --git a/curriculum/challenges/english/blocks/lecture-working-with-common-data-structures-js/699bf563af9132c9e3807638.md b/curriculum/challenges/english/blocks/lecture-working-with-common-data-structures-js/699bf563af9132c9e3807638.md
new file mode 100644
index 00000000000..a59e35f6cde
--- /dev/null
+++ b/curriculum/challenges/english/blocks/lecture-working-with-common-data-structures-js/699bf563af9132c9e3807638.md
@@ -0,0 +1,236 @@
+---
+id: 699bf563af9132c9e3807638
+title: What Are Good Problem-Solving Techniques and Ways to Approach Algorithmic Challenges?
+challengeType: 19
+dashedName: what-are-good-problem-solving-techniques-and-ways-to-approach-algorithmic-challenges
+---
+
+# --description--
+
+During your learning journey, you should work on developing strong problem-solving skills. These core skills will be essential for tackling real-world problems in your daily work.
+
+Solving algorithmic challenges is a great way to practice. It requires an analytical way of thinking, being able to break the problem down into its core components, and finding a solution that generates the right output efficiently.
+
+But where do you start?
+
+There are several problem-solving techniques that you can use to start approaching these challenges.
+
+As an example, we'll reverse a string in JavaScript.
+
+This is the challenge:
+
+"Given a string, write an algorithm that returns a new string with the characters in reverse order."
+
+The first thing that you should do when you come across this type of problem is to read the description multiple times to make sure that you understand what it says. You may miss critical information if you skip this step or read it too fast.
+
+Then, once you are familiar with the problem, start breaking it down into its core components.
+
+Ask yourself:
+
+* "What is the input?"
+
+* "What is the expected output?"
+
+* "How can I transform the input into the expected output?"
+
+
+In this problem, you can determine that the input is a string because the challenge starts with "Given a string…"
+
+The output is "a new string with the characters in reverse order."
+
+So you need to take the original string and reverse it.
+
+This initial analysis might seem a bit repetitive at first, but it's very helpful to make sure that you fully understand the requirements.
+
+Then, you should start thinking about how the algorithm that you will develop will transform the input into the output.
+
+During this planning and analysis phase, it's common to use pseudocode to map out the necessary steps.
+
+**Pseudocode** is a high-level description of the algorithm's logic that is general in nature, and is not based on any specific programming language.
+
+Pseudocode is not as formal as actual code, since it's only intended for humans to read. It should be easy to understand at a glance. Its main purpose is to give a clear idea of the sequence of steps that will be performed.
+
+Pseudocode is usually a mixture of a common written language, like English, with programming constructs, like `IF`, `ELSE`, `FOR`, and `WHILE`.
+
+This is an example of pseudocode that you may write to solve the "Reverse a String" challenge.
+
+```md
+GET original_string
+
+SET reversed_string = ""
+
+FOR EACH character IN original_string:
+ ADD character TO THE BEGINNING OF reversed_string
+
+DISPLAY reversed_string
+```
+
+Note how the steps are outlined in a way that is easy to understand. The words and constructs themselves might vary depending on the standards that you are following.
+
+If you wanted to, you could implement these steps in JavaScript or other programming languages following the same logic, since the pseudocode is independent of the programming language.
+
+By this point, you may have already realized that this problem can be solved in many different ways. This isn't the only way to reverse a string.
+
+But remember that choosing the right algorithm is important.
+
+In a previous lesson, you learned about algorithmic complexity and why it is important to choose algorithms that are efficient in terms of time and space.
+
+That's where you will play a vital role as a developer. You will need to choose the most efficient algorithm to solve the challenge.
+
+Thinking through different available algorithms is an important problem-solving skill that you should practice. Take a moment to ask yourself if the solution that you are proposing in your pseudocode is the best one or not.
+
+For example, there are many different algorithms for sorting elements, but some of them are more efficient than others. Bubble sort, for example, is very inefficient for sorting large lists, while Quick Sort is usually more efficient.
+
+For our "Reverse a String" challenge, we could use either one of these approaches, assuming that we are planning to implement our algorithm in JavaScript:
+
+* Using built-in methods like `.split("")`, `.reverse()`, and `.join("")` to return a new reversed string.
+
+* Looping over the characters from left to right and adding the new character to the beginning of the new string.
+
+* Converting the string into an array and manually reversing it with a loop before joining it back into a string.
+
+
+Which one should you use? That's your choice.
+
+Making these decisions based on your knowledge and experience can make a huge difference in the final performance of your application. Consider different approaches, their efficiency, implications, and implementation.
+
+Ask yourself:
+
+* "How will I approach this problem?"
+
+* "What data structures will I use?"
+
+* "Are the data structures that I chose the most efficient ones for the problem at hand?"
+
+* "Am I covering all possible edge cases?"
+
+
+Edge cases are specific, valid inputs or conditions that occur at the boundaries of what an algorithm should handle.
+
+For example, in the "Reverse a String" challenge, an edge case would be taking an empty string as input. Are you handling this correctly? If not, consider the best way to handle this edge case and add it to your pseudocode.
+
+Then, once you are happy with your plan, you can move on to the implementation phase. At this phase, you will implement your algorithm in a programming language.
+
+When structuring your program, you should write modular code that is easy to read and understand.
+
+Use the tools of the programming language based on your current knowledge. Some programming languages include built-in solutions for common problems and tasks. Use them if possible.
+
+To be consistent, follow the best practices of JavaScript or the programming language of your choice.
+
+Test your code as you write it and make sure that you are handling edge cases appropriately.
+
+Once your solution is implemented, check if it works correctly for all the examples and potentially refactor your code to make it clearer or simpler.
+
+Going back to your solution is very important. Development is not necessarily a linear, step-by-step process. You can always go back to your code and use your critical thinking skills to improve it.
+
+These are some common problem-solving techniques that you can follow to approach algorithmic challenges. If you practice consistently, you will gradually develop your problem-solving skills.
+
+# --questions--
+
+## --text--
+
+Which of the following is the most important first step when approaching any problem-solving challenge?
+
+## --answers--
+
+Understand the problem statement, inputs, and constraints.
+
+---
+
+Search for existing solutions online.
+
+### --feedback--
+
+What should you do before you even think about solutions?
+
+---
+
+Immediately start writing code.
+
+### --feedback--
+
+What should you do before you even think about solutions?
+
+---
+
+Guess a solution and then try to make it work.
+
+### --feedback--
+
+What should you do before you even think about solutions?
+
+## --video-solution--
+
+1
+
+## --text--
+
+What is the main purpose of writing pseudocode when solving an algorithmic challenge?
+
+## --answers--
+
+To write the final, executable version of the code.
+
+### --feedback--
+
+Think about what pseudocode helps you do before you start writing code.
+
+---
+
+To test the algorithm's performance and find bugs.
+
+### --feedback--
+
+Think about what pseudocode helps you do before you start writing code.
+
+---
+
+To outline the algorithm's logic in a human-readable, language-agnostic way.
+
+---
+
+To automatically generate the actual code for the solution.
+
+### --feedback--
+
+Think about what pseudocode helps you do before you start writing code.
+
+## --video-solution--
+
+3
+
+## --text--
+
+Before writing the final code for an algorithmic challenge, why is it important to consider edge cases?
+
+## --answers--
+
+Edge cases are always the easiest parts of the problem to solve.
+
+### --feedback--
+
+Think about what kind of inputs might cause unexpected behavior if they are not specifically considered, even if they are valid.
+
+---
+
+They help ensure the algorithm works correctly for all valid inputs.
+
+---
+
+They are only relevant for very simple problems.
+
+### --feedback--
+
+Think about what kind of inputs might cause unexpected behavior if they are not specifically considered, even if they are valid.
+
+---
+
+They make the code shorter.
+
+### --feedback--
+
+Think about what kind of inputs might cause unexpected behavior if they are not specifically considered, even if they are valid.
+
+## --video-solution--
+
+2
diff --git a/curriculum/challenges/english/blocks/lecture-working-with-common-data-structures-js/699bf563af9132c9e3807639.md b/curriculum/challenges/english/blocks/lecture-working-with-common-data-structures-js/699bf563af9132c9e3807639.md
new file mode 100644
index 00000000000..6beb2ee1777
--- /dev/null
+++ b/curriculum/challenges/english/blocks/lecture-working-with-common-data-structures-js/699bf563af9132c9e3807639.md
@@ -0,0 +1,240 @@
+---
+id: 699bf563af9132c9e3807639
+title: How Do Dynamic Arrays Differ From Static Arrays?
+challengeType: 19
+dashedName: how-do-dynamic-arrays-differ-from-static-arrays
+---
+
+# --description--
+
+Arrays are a fundamental data structure in computer science. All arrays store ordered collections of data, but depending on their type, they may work differently behind the scenes.
+
+Their underlying behavior can have an important effect in the program's efficiency, so let's learn about dynamic and static arrays and their differences, so you can choose the most efficient one for your program.
+
+We'll start with static arrays.
+
+**Static arrays** have a fixed size. They store elements in adjacent memory locations.
+
+The size of a static array is determined when the array is initialized. Once that specific block of memory is allocated, it's fixed, and cannot be changed while the program is running. This is a key characteristic of static arrays.
+
+Storing elements in adjacent memory locations makes the data retrieval process more efficient because the program can store the location of the first element and then use indices to make simple calculations and find the other elements in memory.
+
+Thanks to this, accessing the values of a static array takes constant time `O(1)`, which is very efficient.
+
+You can use a static array when you know the number of elements that will be stored in advance. It's also helpful when the values will be accessed very frequently, since the access operation is very efficient.
+
+However, this data structure cannot grow or shrink, so if the number of elements that will be stored can vary, you should use a dynamic array instead.
+
+Trying to increase the size of a static array would involve creating a new array and copying all the elements from the old array to a new one, which is inefficient. In that case, a dynamic array would be much better because it handles this process automatically.
+
+JavaScript does not have traditional low-level static arrays like C or Java, but you can simulate a fixed-size array using the built-in `Array` object:
+
+```js
+let numbers = new Array(3); // fixed size of 3
+numbers[0] = 10;
+numbers[1] = 20;
+numbers[2] = 30;
+```
+
+While JavaScript allows resizing, conceptually this represents a fixed-length array.
+
+Arrays in JavaScript are dynamic by default, so let's take a look at those.
+
+**Dynamic arrays** are more flexible because they can grow or shrink automatically while the program is running.
+
+They work through an automatic resizing mechanism that copies the elements into a new array when the original array is full. The process is done efficiently because the size of the new array is chosen in an efficient way that makes these computationally expensive operations less frequent.
+
+Accessing the elements of a dynamic array takes constant time `O(1)`, so this operation is very efficient.
+
+Inserting an element in the middle of the array takes linear time `O(n)` because the elements after it need to be relocated.
+
+Inserting an element at the end of the array takes constant time `O(1)` if there is still space available in the dynamic array, but if the array is full and needs resizing, this operation has a `O(n)` complexity.
+
+You should use dynamic arrays when you don't know in advance the number of values that you will need to store in the array. They are also helpful when you will be frequently inserting and deleting elements.
+
+To create an array in JavaScript, you write the elements inside square brackets, separated by commas:
+
+```js
+let numbers = [3, 4, 5, 6];
+```
+
+This creates a dynamic array with four elements.
+
+You can access an element in the array by writing the variable name, followed by square brackets containing the index.
+
+Indices start at 0 for the first element and increase by 1 for each next element.
+
+```js
+numbers[0]; // 3
+numbers[1]; // 4
+numbers[2]; // 5
+numbers[3]; // 6
+```
+
+To update a value, you just need to reassign it:
+
+```js
+numbers[2] = 16
+```
+
+Now, the array becomes `[3, 4, 16, 6]`.
+
+To add an element to the end of the array, use the `.push()` method:
+
+```js
+numbers.push(7)
+```
+
+Now the array becomes `[3, 4, 16, 6, 7]`:
+
+To insert elements at a specific index, JavaScript does not have `.insert()` like Python, but you can use the `.splice()` method. The syntax looks like this:
+
+```js
+array.splice(index, deleteCount, newElement)
+```
+
+Here's an example:
+
+```js
+numbers.splice(3, 0, 15);
+```
+
+This example means:
+
+- Start at index 3
+- Remove 0 elements
+- Insert 15
+
+If the array was `[3, 4, 16, 6, 7]`, it now becomes `[3, 4, 16, 15, 6, 7]`.
+
+You can remove an element at a specific index with the same `.splice` method:
+
+```js
+numbers.splice(2, 1);
+```
+
+This means start at index 2 and remove 1 element.
+
+To remove the last element, use the `.pop()` method:
+
+```js
+numbers.pop();
+```
+
+There are tons of other built-in array methods that you can check in the documentation for working with arrays in JavaScript.
+
+That's the power of dynamic arrays.
+
+In general, you should use static arrays when you know the number of elements in advance and you need to access them frequently, and use dynamic arrays when the number of elements is unknown or variable over time.
+
+You should always consider the tradeoff between the simplicity of static arrays and the flexibility of dynamic arrays. They are both helpful for specific use cases and scenarios. Being able to choose the best one for a given problem is part of the problem-solving skills that you will gradually develop with practice.
+
+# --questions--
+
+## --text--
+
+What is the main difference in size between a static array and a dynamic array?
+
+## --answers--
+
+Static arrays can change their size after being created, while dynamic arrays cannot.
+
+### --feedback--
+
+Think about how much space each type of array will require.
+
+---
+
+Static arrays have a fixed size, while dynamic arrays can change size during runtime.
+
+---
+
+There is no practical difference in how their sizes are handled.
+
+### --feedback--
+
+Think about how much space each type of array will require.
+
+---
+
+Dynamic arrays are always larger than static arrays.
+
+### --feedback--
+
+Think about how much space each type of array will require.
+
+## --video-solution--
+
+2
+
+## --text--
+
+If you need to add more elements to a static array that is already full, what is the typical process involved?
+
+## --answers--
+
+The static array automatically expands its memory to fit the new elements.
+
+### --feedback--
+
+Think about what is necessary when a container with a fixed capacity runs out of space.
+
+---
+
+You must create a new, larger array and copy all existing elements to it.
+
+---
+
+The array automatically converts itself into a dynamic array.
+
+### --feedback--
+
+Think about what is necessary when a container with a fixed capacity runs out of space.
+
+---
+
+New elements are simply discarded if the array is full.
+
+### --feedback--
+
+Think about what is necessary when a container with a fixed capacity runs out of space.
+
+## --video-solution--
+
+2
+
+## --text--
+
+In which scenario would a static array typically be a more suitable choice than a dynamic array?
+
+## --answers--
+
+When the exact number of elements is unknown and changes frequently.
+
+### --feedback--
+
+Think about the main advantage of a static array related to its size and resource usage.
+
+---
+
+When you need to store a very large dataset that might grow indefinitely.
+
+### --feedback--
+
+Think about the main advantage of a static array related to its size and resource usage.
+
+---
+
+When you require frequent insertions and deletions at arbitrary positions within the collection.
+
+### --feedback--
+
+Think about the main advantage of a static array related to its size and resource usage.
+
+---
+
+When the data size is fixed and known at the time the program is written.
+
+## --video-solution--
+
+4
diff --git a/curriculum/challenges/english/blocks/lecture-working-with-common-data-structures-js/699bf563af9132c9e380763a.md b/curriculum/challenges/english/blocks/lecture-working-with-common-data-structures-js/699bf563af9132c9e380763a.md
new file mode 100644
index 00000000000..06750df7dad
--- /dev/null
+++ b/curriculum/challenges/english/blocks/lecture-working-with-common-data-structures-js/699bf563af9132c9e380763a.md
@@ -0,0 +1,194 @@
+---
+id: 699bf563af9132c9e380763a
+title: How Do Stacks and Queues Work?
+challengeType: 19
+dashedName: how-do-stacks-and-queues-work
+---
+
+# --description--
+
+Stacks and queues are data structures commonly used in computer science.
+
+They're linear data structures that follow specific rules for adding and removing elements.
+
+## Stacks
+
+Let's start with **Stacks**.
+
+A **stack** is a Last-in, First-out (LIFO) data structure.
+
+This means that the last element that was added to the stack is the first one to be removed.
+
+Stacks have two ends, which we know as top and bottom.
+
+Elements are added and removed from the top of the stack.
+
+You can think of a stack as a pile of dishes, where you can only place dishes at the top of the pile and take dishes from the top of the pile.
+
+
+
+These operations of adding and removing elements have special names in this context.
+
+Adding an element to a stack is known as a "push" operation. We say that we "push" an element onto the stack when we add it to the top of the stack.
+
+
+
+Removing an element from a stack is known as a "pop" operation. We say that we "pop" an element from the stack when we remove it from the top of the stack.
+
+
+
+You can see that we don't really perform any operations at the bottom of the stack but we keep it there as a reference.
+
+The time complexity of the push and pop operations is typically `O(1)`, a constant time complexity.
+
+When you push an element onto the stack, the element is simply added to the top.
+
+When you pop an element from the stack, the element at the top is removed.
+
+Therefore, the time it takes to perform these operations remains constant regardless of the size of the stack.
+
+The space complexity of the push and pop operations is usually constant `O(1)`. This means that the amount of memory required to perform these operations remains constant regardless of the size of the stack.
+
+## Queues
+
+Now that you know more about stacks, let's learn about **Queues**.
+
+A queue is a First-in First-out (FIFO) linear data structure. This means that the first element added to the queue is the first one to be removed.
+
+Queues have two ends: front and back.
+
+
+
+Elements are added to the back of the queue and they are removed from the front of the queue.
+
+You can think of a queue as a line of people waiting to pay for their groceries at the supermarket. The first person in line is the first one to go to the cash register while new people join the line at the end.
+
+The operations of adding and removing elements have special names in the context of a queue.
+
+Adding an element to the back of a queue is known as an "enqueue" operation.
+
+In an enqueue operation, the new element is added to the end of the queue, becoming the end of the line.
+
+
+
+Removing an element from the front of the queue is known as a "dequeue" operation.
+
+In the dequeue operation, the element at the front of the queue is removed, and the next element in line becomes the new front.
+
+
+
+The time complexity of the enqueue and dequeue operations is `O(1)`, constant time. The time it takes to perform these operations remains constant, regardless of the size of the queue.
+
+The space complexity of the enqueue and dequeue operations is usually constant `O(1)`. This means that the amount of memory required to perform these operations remains constant regardless of the size of the queue.
+
+Stacks and queues are data structures used in computer science for organizing and managing elements. Understanding them is essential for building efficient algorithms in various programming applications.
+
+# --questions--
+
+## --text--
+
+What is the primary difference between a stack and a queue?
+
+## --answers--
+
+Stacks are LIFO, while queues are FIFO.
+
+---
+
+Stacks are FIFO, while queues are LIFO.
+
+### --feedback--
+
+Think about the order in which elements are added and removed from each data structure.
+
+---
+
+Stacks are used for storing data, while queues are used for processing data.
+
+### --feedback--
+
+Think about the order in which elements are added and removed from each data structure.
+
+---
+
+There is no difference between stacks and queues.
+
+### --feedback--
+
+Think about the order in which elements are added and removed from each data structure.
+
+## --video-solution--
+
+1
+
+## --text--
+
+Which operation is used to add an element to a stack?
+
+## --answers--
+
+`push`
+
+---
+
+`pop`
+
+### --feedback--
+
+Think about the analogy of a stack of plates.
+
+---
+
+`enqueue`
+
+### --feedback--
+
+Think about the analogy of a stack of plates.
+
+---
+
+`dequeue`
+
+### --feedback--
+
+Think about the analogy of a stack of plates.
+
+## --video-solution--
+
+1
+
+## --text--
+
+Which operation is used to remove an element from a queue?
+
+## --answers--
+
+`push`
+
+### --feedback--
+
+Think about the analogy of a line of people waiting.
+
+---
+
+`pop`
+
+### --feedback--
+
+Think about the analogy of a line of people waiting.
+
+---
+
+`enqueue`
+
+### --feedback--
+
+Think about the analogy of a line of people waiting.
+
+---
+
+`dequeue`
+
+## --video-solution--
+
+4
diff --git a/curriculum/challenges/english/blocks/lecture-working-with-common-data-structures-js/699bf563af9132c9e380763b.md b/curriculum/challenges/english/blocks/lecture-working-with-common-data-structures-js/699bf563af9132c9e380763b.md
new file mode 100644
index 00000000000..a5406100e74
--- /dev/null
+++ b/curriculum/challenges/english/blocks/lecture-working-with-common-data-structures-js/699bf563af9132c9e380763b.md
@@ -0,0 +1,230 @@
+---
+id: 699bf563af9132c9e380763b
+title: How Do Singly Linked Lists Work and How Do They Differ From Doubly Linked Lists?
+challengeType: 19
+dashedName: how-do-singly-linked-lists-work-and-how-do-they-differ-from-doubly-linked-list
+---
+
+# --description--
+
+A **linked list** is a linear data structure in which each node is connected to the next node in the sequence.
+
+These connections create a data structure that looks like a chain of nodes, where each node stores data and a reference to the next node in the linked list.
+
+
+
+We use these references to go from the first node to the next node and so on.
+
+Linked lists are commonly used for implementing other data structures, such as stacks, queues, and deques. They can also be used to implement essential graph algorithms, such as depth-first search and breadth-first search.
+
+## Singly Linked Lists
+
+A **singly linked list** is a type of linked list in which each node is connected to the next node in the sequence.
+
+Each node is connected to the next one by storing a reference to it.
+
+This single reference per node allows you to traverse the linked list in one direction, from start to end.
+
+The search can only move forward, not backwards.
+
+In this example, you would start at the head node, node A.
+
+The **head** node is the first node in the linked list.
+
+In a singly linked list, the head node is usually the only node that is directly accessible. This is where the search process will start when you're trying to find a specific node.
+
+
+
+The process will start at node A, then it will continue to node B, then node C, and finally node D, the **tail** node. It may also stop before that if you implement specific logic in your code.
+
+The **tail** node is the last node. It's used to determine when the process has reached the end of the linked list.
+
+### **Inserting Nodes**
+
+One of the great things about linked lists is that they do not have a fixed size. They can be expanded or shrunk as needed by simply updating the connections between the nodes.
+
+You can **insert** a node at the start, middle, and end of a linked list.
+
+Linked lists don't necessarily need to store the nodes in a specific order. The order will be determined by the connections between the nodes.
+
+However, if you do need to keep the nodes in a specific order for your particular use case, you can do so by implementing that logic in your code and the criteria you implement will determine if the node is inserted at the start, middle, or end.
+
+To insert a node at the start of the linked list, you just need to create a connection between the new node and the node that used to be the head node and make the new node the head node instead.
+
+This is an example, where we insert node E at the start and make this new node the head node of the linked list.
+
+
+
+Inserting a node at the beginning of the linked list has a constant time complexity `O(1)` because it only requires updating the reference to the head node and the connection between the new head node and the next node in the sequence.
+
+In this example, we are inserting node E at the start of the linked list. This will work correctly. But if we wanted to keep the linked list sorted in alphabetical order, node E would have to be inserted at the end of the linked list instead.
+
+To insert a node at the end of the linked list, first you need to reach the end and then add a connection to the new node to make it the new tail node.
+
+This operation has linear time complexity, `O(n)`, where n is the number of nodes stored in the linked list, because first you need to reach the end of the linked list to make the insertion and this would require going from one node to the next and so on until the end is reached.
+
+
+
+If the node has to be inserted somewhere in the middle of the linked list, the connections between the nodes will have to be updated too. The previous node in the sequence should be connected to the new node and the new node should be connected to the next node, like in the following diagram.
+
+
+
+The insertion operation has a constant space complexity `O(1)`, since inserting a new node only requires creating it and updating the connections between the nodes. This operation doesn't depend on the size of the linked list itself.
+
+### **Removing Nodes**
+
+Just as you can insert nodes, you can also remove them from the start, middle, and end of the linked list.
+
+To remove a node from the start, you need to update the reference to the head node, which should be the next node in the sequence.
+
+This operation has a constant time complexity `O(1)`, because it only requires updating the linked list's reference to the head node.
+
+
+
+To remove a node from the middle of the linked list, you need to update the reference of the previous node to connect it to the next node in the sequence, forming a sort of "bridge" between them, as you can see in this diagram.
+
+
+
+That will remove the node that you want to remove, in this case node B, from the sequence of connections, so it won't be reached the next time you traverse it.
+
+To remove a node from the end of the linked list, you need to remove the connection of the previous node and make this node the new tail node. Now the linked list will end at the new tail node.
+
+This operation has a linear time complexity `O(n)`, because first you have to reach the end of the linked list.
+
+
+
+The deletion operation has a constant space complexity `O(1)`, because no additional memory is required to delete a node.
+
+## Doubly Linked Lists
+
+Now that you know more about singly linked lists, let's talk about doubly linked lists.
+
+In a **doubly linked list**, each node stores two references: a reference to the next node and a reference to the previous node in the sequence.
+
+This means that doubly linked lists can be traversed in both directions.
+
+
+
+In this type of linked list, it's also common to keep a reference to the tail node in the linked list itself to start the traversal from the end if necessary.
+
+That sounds great, right? They're more flexible than singly linked lists.
+
+However, doubly linked lists do require more memory than singly linked lists because each node stores **two** references instead of one.
+
+This is something that you should keep in mind when you're choosing the right data structure for your project.
+
+There **is** a tradeoff.
+
+The insertion and deletion operations work exactly the same. The only difference is that now you will need to update two references per node and keep track of the reference to the tail node to insert elements at the end of the doubly linked list very efficiently and start the traversal process from the back, if necessary.
+
+Singly and doubly linked lists are essential data structures in computer science used for storing and manipulating elements in a sequential order. Understanding their differences is essential for choosing the right one for your specific application.
+
+# --questions--
+
+## --text--
+
+What is a linked list?
+
+## --answers--
+
+A data structure that stores elements in a contiguous block of memory.
+
+### --feedback--
+
+Think about how nodes are connected in a linked list.
+
+---
+
+A data structure where nodes are connected using references.
+
+---
+
+A data structure that is always sorted.
+
+### --feedback--
+
+Think about how nodes are connected in a linked list.
+
+---
+
+A data structure that has a fixed size.
+
+### --feedback--
+
+Think about how nodes are connected in a linked list.
+
+## --video-solution--
+
+2
+
+## --text--
+
+What is the difference between a singly linked list and a doubly linked list?
+
+## --answers--
+
+Singly linked lists have a head and tail node, while doubly linked lists do not.
+
+### --feedback--
+
+Think about the references contained in each type of linked list.
+
+---
+
+Singly linked lists can only be traversed in one direction, while doubly linked lists can be traversed in both directions.
+
+---
+
+Singly linked lists are more efficient to insert elements at the end, while doubly linked lists are more efficient to insert elements at the beginning.
+
+### --feedback--
+
+Think about the references contained in each type of linked list.
+
+---
+
+Singly linked lists require more memory than doubly linked lists.
+
+### --feedback--
+
+Think about the references contained in each type of linked list.
+
+## --video-solution--
+
+2
+
+## --text--
+
+What is the time complexity of inserting a node at the beginning of a singly linked list?
+
+## --answers--
+
+`O(1)`
+
+---
+
+`O(n)`
+
+### --feedback--
+
+Think about the number of operations required to insert a node at the beginning of the linked list.
+
+---
+
+`O(n^2)`
+
+### --feedback--
+
+Think about the number of operations required to insert a node at the beginning of the linked list.
+
+---
+
+`O(log n)`
+
+### --feedback--
+
+Think about the number of operations required to insert a node at the beginning of the linked list.
+
+## --video-solution--
+
+1
diff --git a/curriculum/structure/blocks/lecture-working-with-common-data-structures-js.json b/curriculum/structure/blocks/lecture-working-with-common-data-structures-js.json
new file mode 100644
index 00000000000..4c99c9b0981
--- /dev/null
+++ b/curriculum/structure/blocks/lecture-working-with-common-data-structures-js.json
@@ -0,0 +1,30 @@
+{
+ "name": "Working with Common Data Structures",
+ "isUpcomingChange": true,
+ "dashedName": "lecture-working-with-common-data-structures-js",
+ "helpCategory": "JavaScript",
+ "blockLayout": "challenge-list",
+ "challengeOrder": [
+ {
+ "id": "699bf504558ca3acf83b4732",
+ "title": "What Is an Algorithm and How Does Big O Notation Work?"
+ },
+ {
+ "id": "699bf563af9132c9e3807638",
+ "title": "What Are Good Problem-Solving Techniques and Ways to Approach Algorithmic Challenges?"
+ },
+ {
+ "id": "699bf563af9132c9e3807639",
+ "title": "How Do Dynamic Arrays Differ From Static Arrays?"
+ },
+ {
+ "id": "699bf563af9132c9e380763a",
+ "title": "How Do Stacks and Queues Work?"
+ },
+ {
+ "id": "699bf563af9132c9e380763b",
+ "title": "How Do Singly Linked Lists Work and How Do They Differ From Doubly Linked Lists?"
+ }
+ ],
+ "blockLabel": "lecture"
+}
diff --git a/curriculum/structure/superblocks/javascript-v9.json b/curriculum/structure/superblocks/javascript-v9.json
index 19bcc75b6b3..751fd2f29fc 100644
--- a/curriculum/structure/superblocks/javascript-v9.json
+++ b/curriculum/structure/superblocks/javascript-v9.json
@@ -295,7 +295,11 @@
"quiz-recursion"
]
},
- { "dashedName": "data-structures", "comingSoon": true, "blocks": [] },
+ {
+ "dashedName": "data-structures",
+ "comingSoon": true,
+ "blocks": ["lecture-working-with-common-data-structures-js"]
+ },
{
"dashedName": "algorithms",
"comingSoon": true,