JavaScript Coding Test Course, What Algorithm Should I Use?

Coding tests are an important gateway for developers. Especially for developers using JavaScript, it is crucial to have a good understanding of the characteristics of this language and algorithms. In this course, we will select one algorithm problem using JavaScript and explain the process of solving it step by step.

Problem Description

Problem: Two Sum

This problem involves finding two numbers in a given integer array such that their sum equals a specific target value, and returning the indices of those two numbers.

Example:
    Input: nums = [2, 7, 11, 15], target = 9
    Output: [0, 1]
    Explanation: nums[0] + nums[1] = 2 + 7 = 9, thus it returns [0, 1].
    

Problem Analysis

This problem can generally be solved in O(n) time complexity using a hash map. By iterating through all elements of the array, we check the difference between each element and the target value, and store the corresponding indices.

Approach

  1. Create a hash map (object) to store each element of the array.
  2. While iterating through the array, calculate the difference between each element’s value and the target value.
  3. Check if a value corresponding to this difference exists in the hash map.
  4. If it exists, return the corresponding index and the current index.

JavaScript Code

function twoSum(nums, target) {
        const map = new Map();
        
        for (let i = 0; i < nums.length; i++) {
            const complement = target - nums[i];
            if (map.has(complement)) {
                return [map.get(complement), i];
            }
            map.set(nums[i], i);
        }
        
        throw new Error("No two sum solution");
    }

Code Explanation

The code above works in the following way:

  • It creates a hash map `map`. This is where each number and its index are stored.
  • It checks each element of the array through a loop, calculating the difference with the target value.
  • If this difference exists as a key in the hash map, it returns the index of that key and the current index.
  • If no result is found after checking all elements, it throws an error.

Time Complexity Analysis

The above algorithm has a time complexity of O(n) since it only iterates through all elements of the array once. The insertion and lookup operations for the hash map have an average time complexity of O(1), making it an efficient solution overall.

Space Complexity Analysis

The space complexity is O(n), as it may require this amount of space to store all elements of the array in the hash map.

Conclusion

Such problems are frequently presented in coding tests. When approaching each problem, it is important to consider efficient algorithms and data structures. By utilizing hash maps as shown above, you can achieve good performance in solving problems.

Tips for Future Algorithm Problem Solving

1. Learn about various data structures and algorithms.
2. Practice recognizing specific patterns when solving problems.
3. Learn from others' approaches through code reviews.
4. Solve problems on online platforms and receive feedback.
5. Regularly practice coding to maintain and improve your skills.

JavaScript Coding Test Course, Gift Giving

Problem Description

You are in charge of delivering gifts to several friends. To deliver gifts to each friend, you need their unique ID. When given the ID of all friends and the ID of gifts, you need to determine whether the gifts can be delivered.

Problem Definition

Each friend is assumed to have the following information:

  • Friend’s ID
  • ID of the gift they want
  • Signal (whether this friend can receive the gift or not)

The input array contains information about several friends. Based on each friend’s ID and the ID of the gift they want, write a function to determine whether the gifts can be delivered accurately.

Input Format


    [
        { friendId: 1, giftId: 101, signal: true },
        { friendId: 2, giftId: 102, signal: false },
        { friendId: 3, giftId: 101, signal: true }
    ]
    

Output Format


    [
        { friendId: 1, giftId: 101, canReceive: true },
        { friendId: 2, giftId: 102, canReceive: false },
        { friendId: 3, giftId: 101, canReceive: true }
    ]
    

Solution Method

To solve this problem, you need to iterate through the array containing each friend’s information and determine if they can receive the gift. Basically, if the friend’s ID and the gift’s ID match, it’s assumed that they can receive the gift. However, if the friend’s signal value is false, they cannot receive the gift, so this needs to be taken into account.

Algorithm Explanation


    function canGiftsBeReceived(friends) {
        return friends.map(friend => {
            const canReceive = (friend.signal === true && friend.friendId === friend.giftId);
            return { ...friend, canReceive: canReceive };
        });
    }
    

The code above takes the given friends’ information and determines whether each friend can receive the gift, returning a new array.

Detailed Steps

  1. Function Definition: Define a function named canGiftsBeReceived that takes a parameter friends. This parameter is an array containing friends’ information.
  2. Iterate Through Array: Use the map method to iterate through the given friends array. Use a local variable named friend for each friend.
  3. Condition Check: For each friend, check if signal is true and if friendId matches giftId, saving the result in the canReceive value.
  4. Create Result Object: Create a new object based on each friend’s information. This object includes the existing friend information and the canReceive value.
  5. Return Result: Finally, return the transformed array.

Example Code


    const friends = [
        { friendId: 1, giftId: 101, signal: true },
        { friendId: 2, giftId: 102, signal: false },
        { friendId: 3, giftId: 101, signal: true }
    ];

    const result = canGiftsBeReceived(friends);
    console.log(result);
    

Result


    [
        { friendId: 1, giftId: 101, signal: true, canReceive: true },
        { friendId: 2, giftId: 102, signal: false, canReceive: false },
        { friendId: 3, giftId: 101, signal: true, canReceive: true }
    ]
    

The results above clearly show whether each friend can receive the gift. This method ensures safe delivery of gifts.

Conclusion

In this lecture, we explored a problem-solving method using basic arrays and objects. To solve algorithmic problems, it’s important to systematically analyze the problem and apply the appropriate algorithm. I hope this helps you tackle various problems using JavaScript.

© 2023 Algorithm Problem-Solving Course

Javascript Coding Test Course, Selection Sort

1. Introduction

In coding tests and algorithm problem-solving, sorting algorithms are an essential topic to learn. Among various methods of sorting arrays, Selection Sort is considered a good algorithm to learn in the initial stages due to its simple implementation and intuitive process. In this tutorial, we will explore the concept and principles of Selection Sort, as well as how to implement it in JavaScript in detail.

2. What is Selection Sort?

Selection Sort is a simple algorithm for sorting arrays that operates by repeatedly finding the smallest (or largest) value in the given array and swapping it with the current position. This algorithm works by dividing the process into sorted and unsorted sections with each iteration.

2.1. How It Works

Selection Sort operates as follows:

  • Starting from the first element of the array, find the smallest element among the remaining elements and swap it with the first element.
  • Repeat the same process starting from the second element, swapping the second element with the smallest element among the second and subsequent elements.
  • Continue this process until the last element of the array.

2.2. Time Complexity of Selection Sort

The time complexity of Selection Sort is O(n²) in both the worst and average cases. This means that performance can degrade sharply depending on the size of the array. Therefore, Selection Sort is most suitable for use with small datasets.

3. Implementing Selection Sort

In this section, we will implement Selection Sort in JavaScript.

3.1. Basic Implementation

The code below is a basic JavaScript function implementing Selection Sort:


function selectionSort(arr) {
    const n = arr.length;

    for (let i = 0; i < n - 1; i++) {
        // Initialize the current index (i) as a candidate
        let minIndex = i;

        // Scan the remaining array to find the index of the smallest element
        for (let j = i + 1; j < n; j++) {
            if (arr[j] < arr[minIndex]) {
                minIndex = j; // Update minIndex if a smaller value is found
            }
        }

        // Swap the candidate minimum value with the current position (i)
        // Swap only if the current position is not the minimum
        if (minIndex !== i) {
            [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];
        }
    }

    return arr;
}

// Example usage
const unsortedArray = [64, 25, 12, 22, 11];
const sortedArray = selectionSort(unsortedArray);
console.log(sortedArray); // [11, 12, 22, 25, 64]
    

3.2. Code Explanation

The code above is a function that uses the Selection Sort algorithm. Let’s analyze the function step by step:

  1. const n = arr.length;: This calculates the length of the array.
  2. for (let i = 0; i < n - 1; i++): The first loop iterates through each element of the array.
  3. let minIndex = i;: This initializes the index of the current smallest value.
  4. for (let j = i + 1; j < n; j++): The second loop iterates through the remaining array to find the index of the smallest element.
  5. if (arr[j] < arr[minIndex]) { minIndex = j; }: If the current element of the array is less than the current minimum, it updates the index of the minimum value.
  6. if (minIndex !== i) { [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]]; }: Finally, if the minimum value is not at the current index, it performs the swap.

4. Optimized Selection Sort

The basic Selection Sort can be optimized. By reducing unnecessary swaps, we can improve performance slightly. For instance, adding a check to see if sorting is already complete and terminating the loop when no further swaps are needed can enhance performance. The code below shows the optimized Selection Sort:


function optimizedSelectionSort(arr) {
    const n = arr.length;
    let isSorted = true;

    for (let i = 0; i < n - 1; i++) {
        let minIndex = i;

        for (let j = i + 1; j < n; j++) {
            if (arr[j] < arr[minIndex]) {
                minIndex = j;
                isSorted = false; // Remember that a swap will occur
            }
        }

        if (minIndex !== i) {
            [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];
        }

        // Exit the loop if the array is already sorted
        if (isSorted) break;
    }

    return arr;
}

// Example usage
const unsortedArray = [64, 25, 12, 22, 11];
const sortedArray = optimizedSelectionSort(unsortedArray);
console.log(sortedArray); // [11, 12, 22, 25, 64]
    

4.1. Optimization Explanation

The optimized Selection Sort function uses let isSorted = true; in the initialization stage to track whether the array is sorted. After each iteration, if an actual swap occurs in the array, this flag is set to false. If no swap occurs in the current iteration, it indicates that the array is fully sorted, and the loop is exited.

5. Practical Example

Let me show you an example of sorting actual data using Selection Sort, such as sorting student grade data. This can help compare students’ scores or provide necessary information.


const students = [
    { name: "Emily", score: 85 },
    { name: "David", score: 92 },
    { name: "Sophie", score: 76 },
    { name: "John", score: 89 },
    { name: "Max", score: 90 },
];

function selectionSortByScore(arr) {
    const n = arr.length;
    for (let i = 0; i < n - 1; i++) {
        let minIndex = i;
        for (let j = i + 1; j < n; j++) {
            if (arr[j].score < arr[minIndex].score) {
                minIndex = j;
            }
        }
        if (minIndex !== i) {
            [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];
        }
    }
    return arr;
}

const sortedStudents = selectionSortByScore(students);
console.log(sortedStudents);
    

5.1. Practical Example Explanation

The code above demonstrates how to sort an array based on students’ scores. Each student is represented as an object with a name and score, and the selectionSortByScore function sorts them in ascending order of scores and provides the output.

6. Conclusion

Selection Sort is a simple implementation that is very useful for beginners to understand the basic principles of algorithms. However, due to its O(n²) time complexity, its efficiency decreases with large datasets, and it is recommended to use better algorithms such as Quick Sort or Merge Sort in real production environments. Nevertheless, building a foundation in algorithms through Selection Sort is an important learning process. I hope this knowledge will be of great help in preparing for coding tests.

JavaScript Coding Test Course, Calculating the Amount of Water

In this lecture, we will address the problem of ‘Calculating the Amount of Water’, which is commonly featured in coding tests, using JavaScript. This problem will provide a great opportunity to learn various algorithm design patterns and utilize arrays effectively.

Problem Definition

The problem is to calculate the amount of water that can be collected when it rains, given an array of heights of bars. The heights of the bars are provided as each element of the array.

For example, if the array is [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1], the amount of water that can be collected is 6. Visually representing how water is stored between each bar in this example is as follows:

Water Storage Visualization

Approaches to Solve the Problem

There are various methods that can be used to solve this problem. The two most commonly used approaches are as follows.

  1. Two Pointers Method

    This method progresses by moving two pointers inwards from both ends. Each pointer tracks the height from the left and right, allowing calculation of positions where water can accumulate.

  2. Dynamic Programming

    This method involves finding the tallest bar from both left and right at each position, using the shorter of the two to calculate the amount of water. However, this method has the drawback of using a lot of additional memory.

Solving the Problem with JavaScript

First, let’s implement the code using the two pointers method. We will create an algorithm that starts from both ends of the array and moves towards the center to calculate the amount of water.

Code Example


function trap(height) {
    if (height.length === 0) return 0;

    let left = 0;
    let right = height.length - 1;
    let leftMax = 0;
    let rightMax = 0;
    let waterTrapped = 0;

    while (left < right) {
        if (height[left] < height[right]) {
            if (height[left] >= leftMax) {
                leftMax = height[left];
            } else {
                waterTrapped += leftMax - height[left];
            }
            left++;
        } else {
            if (height[right] >= rightMax) {
                rightMax = height[right];
            } else {
                waterTrapped += rightMax - height[right];
            }
            right--;
        }
    }

    return waterTrapped;
}

            

The above function takes the height array as input and calculates the amount of water that can be collected after it rains.

Code Explanation

Let’s take a step-by-step look at the above code:

  1. Initialization: left is initialized to 0, and right is initialized to the last index of the array (length – 1). leftMax and rightMax store the maximum heights from their respective directions. waterTrapped indicates the final amount of water collected.
  2. Loop Execution: The loop runs until left is less than right. In each iteration, the heights from the left and right are compared to calculate the amount of water from the lower side.
  3. Water Calculation: If the height from the left is lower, it compares the maximum height on the left with the current height to calculate the amount of water that can be stored. Similarly, the same operation is performed on the right side.
  4. Return Result: After all loops are completed, it returns the waterTrapped variable to output the final result.

Code Testing

Now, let’s test the algorithm we’ve written. We can verify the performance of the function through several examples like the following:


console.log(trap([0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1])); // 6
console.log(trap([4, 2, 0, 3, 2, 5])); // 9
console.log(trap([])); // 0
console.log(trap([1, 0, 1])); // 1

            

Each output should match the predicted amount of water. The following results will be displayed:

  • trap([0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]) – 6
  • trap([4, 2, 0, 3, 2, 5]) – 9
  • trap([]) – 0
  • trap([1, 0, 1]) – 1

Performance Analysis

The algorithm above has a time complexity of O(n) and a space complexity of O(1). This means that the execution time and space required are proportional to the size of the input array. Therefore, it works efficiently even with large amounts of data.

If dynamic programming is used, it requires an additional array to store heights, resulting in a space complexity of O(n). However, the time complexity remains O(n) as well.

Conclusion

In this lecture, we discussed the ‘Calculating the Amount of Water’ problem and introduced how to solve it using JavaScript. By using the two pointers algorithm, we effectively tackled the problem and also conducted code implementation and performance analysis.

This problem includes important concepts that can be applied to other algorithm problems, so practicing other similar problems can further enhance your algorithm skills.

This concludes the JavaScript coding test lecture. I hope it helps you improve your coding skills!

Javascript Coding Test Course, Let’s Try DDR

Many companies evaluate the algorithm and problem-solving abilities of applicants through coding tests. In this article, we will solve an algorithm problem that implements the DDR (Dance Dance Revolution) game using JavaScript.

This article will detail the understanding of the problem, solution methods, code writing, and testing process.

Problem Description

Here is a simple version of the DDR game. The game proceeds in the following format.

The user must press the corresponding keys based on the four arrows shown below:

  • ↑ (Up)
  • ↓ (Down)
  • ← (Left)
  • → (Right)

The goal of the game is to score points by accurately pressing the keys in the order of the given arrow inputs. If a wrong arrow is pressed, the user loses points.

You need to write a function that receives user input and calculates the score when given n arrows. This function adds 1 point for each correct input matching the answer sequence and subtracts 1 point for each incorrect input.

Input Format

        - Arrow array: ["↑", "↓", "←", "→"]
        - User input array: ["↑", "↑", "←", "→", "↓"]
        

Output Format

Returns the user’s final score.

Problem Solving Process

To solve this problem, let’s first design the algorithm. The steps to solve the problem are as follows.

  1. Declare the arrow array and user input array.
  2. Initialize a variable to maintain the score.
  3. Iterate over user inputs and compare each input with the correct answers.
  4. If the input is correct, increase the score by 1; if incorrect, decrease it by 1.
  5. After checking all inputs, return the final score.

Now that the algorithm is clear, let’s write the code.

Code Implementation


function calculateScore(correctArrows, userArrows) {
    let score = 0;

    for (let i = 0; i < userArrows.length; i++) {
        if (userArrows[i] === correctArrows[i]) {
            score += 1; // Correct
        } else {
            score -= 1; // Incorrect
        }
    }

    return score; // Return final score
}

// Example usage
const correctArrows = ["↑", "↓", "←", "→"];
const userArrows = ["↑", "↑", "←", "→", "↓"];

const finalScore = calculateScore(correctArrows, userArrows);
console.log("Final score is:", finalScore);
        

Code Explanation

Let’s explain the code step by step.

1. Function Definition

The function calculateScore takes the arrow array and user input array as parameters. It initializes the score variable to 0 for score calculation.

2. Checking with Loop

Using a for loop, we iterate through the user input array. We check if each user’s input matches the correct arrows.

If they match, we add 1 point; if they do not match, we subtract 1 point.

3. Return Final Score

After checking all user inputs, we return the score value. This value is the final score.

Code Testing

To verify that the code works correctly, let’s create some test cases.

Test Case 1


const correct1 = ["↑", "↓", "←", "→"];
const user1 = ["↑", "↓", "←", "→"];

console.log("Test Case 1 - Score:", calculateScore(correct1, user1)); // 4
        

Test Case 2


const correct2 = ["↑", "↓", "←", "→"];
const user2 = ["↑", "↑", "←", "→", "↓"];

console.log("Test Case 2 - Score:", calculateScore(correct2, user2)); // 2
        

Test Case 3


const correct3 = ["↑", "↓", "←", "→"];
const user3 = ["→", "→", "→", "→"];

console.log("Test Case 3 - Score:", calculateScore(correct3, user3)); // -4
        

Conclusion

In this article, we solved a basic algorithm problem of the DDR game using JavaScript. We were able to solidify the basics of JavaScript through basic problem-solving methods and code writing.

This simple algorithm problem is one of the common types of problems that appear in interviews. Therefore, it’s beneficial to solve many similar problems and develop your own coding style. Thank you!