JavaScript Coding Test Course, Sorting Numbers

Overview

One of the common problems seen in coding tests is sorting a given number.
In this course, we will learn how to sort numbers using JavaScript.
The problem of sorting numbers is very useful for studying basic sorting algorithms.
We can sort numbers using various algorithms, each with different time and space complexities.

Problem Description

Problem

Write a function that takes an array of given numbers as input and returns a sorted array.
For example, if the input array is [3, 1, 2],
the output should be [1, 2, 3].

Input

  • The first line contains an integer N. (1 ≤ N ≤ 100,000)
  • The second line contains N integers A1, A2, ..., AN separated by a single space.
    (-1,000,000 ≤ Ai ≤ 1,000,000)

Output

You must print the sorted numbers in one line, separated by a single space.

Example

    Input:
    5
    5 4 3 2 1
    
    Output:
    1 2 3 4 5
    

Problem Solving Process

Step 1: Requirements Analysis

To solve the given problem, the goal is to sort the input array and output it.
To do this, we can use classic sorting algorithms such as
Quick Sort and Merge Sort.
While we can use built-in JavaScript functions, it is important this time to implement the algorithms ourselves for understanding.

Step 2: Algorithm Selection

Among the sorting algorithms, Quick Sort and Merge Sort are generally widely used fast sorting algorithms.
Below, I will summarize the advantages and disadvantages of each algorithm.

Quick Sort

  • Average time complexity: O(N log N)
  • Worst-case time complexity: O(N2) (with inefficient pivot selection)
  • Space complexity: O(log N)
  • Advantages: Can perform in-place sorting with low memory usage.
  • Disadvantages: It is not a stable sort.

Merge Sort

  • Average and worst-case time complexity: O(N log N)
  • Space complexity: O(N)
  • Advantages: It is a stable sort.
  • Disadvantages: Requires additional memory.

Step 3: Implementing Quick Sort

We will implement a function to sort an array of numbers using Quick Sort.
Below is the implementation code for Quick Sort written in JavaScript.


    function quickSort(arr) {
        if (arr.length <= 1) return arr;
        const pivot = arr[arr.length - 1];
        const left = [];
        const right = [];
        
        for (let i = 0; i < arr.length - 1; i++) {
            if (arr[i] < pivot) {
                left.push(arr[i]);
            } else {
                right.push(arr[i]);
            }
        }
        return [...quickSort(left), pivot, ...quickSort(right)];
    }
    

Step 4: Implementing Merge Sort

Next, let's implement the Merge Sort algorithm. Below is the implementation code for Merge Sort.


    function mergeSort(arr) {
        if (arr.length <= 1) return arr;
        const mid = Math.floor(arr.length / 2);
        const left = mergeSort(arr.slice(0, mid));
        const right = mergeSort(arr.slice(mid));
        
        return merge(left, right);
    }
    
    function merge(left, right) {
        const result = [];
        let i = 0, j = 0;
        
        while (i < left.length && j < right.length) {
            if (left[i] < right[j]) {
                result.push(left[i]);
                i++;
            } else {
                result.push(right[j]);
                j++;
            }
        }
        return result.concat(left.slice(i)).concat(right.slice(j));
    }
    

Step 5: Handling Input and Output

Now that we have completed the sorting functions, we will implement the part that handles input and outputs the result. In JavaScript,
we can use prompt to receive input, and
the result can be printed using console.log.


    const N = parseInt(prompt("Enter the number of integers:"));
    const nums = prompt("Enter the integers:").split(" ").map(Number);
    const sorted = quickSort(nums); // or mergeSort(nums);
    
    console.log(sorted.join(" "));
    

Conclusion

In this course, we solved the problem of sorting a given array of numbers using JavaScript.
We learned not only the implementation of sorting algorithms but also the characteristics and performance of each algorithm.
By directly implementing Quick Sort and Merge Sort, we were able to deepen our understanding of sorting algorithms.
In coding tests, various problems are presented aside from sorting problems, so I recommend practicing these algorithms in various ways.

Problem Solving and Practice

Solve the following problems for more practice!

  • Remove duplicate numbers from the given array and then sort it
  • Interval sorting: sort only within a given interval
  • Problem of merging two sorted arrays

References

JavaScript Coding Test Course, Greedy Algorithm

A Greedy Algorithm is an algorithm that makes the most suitable choice at every moment to find the optimal solution. It aims to make choices that seem optimal at each step to optimize the overall problem, although this choice does not always guarantee the optimal solution to the entire problem. However, it is often used because there are many cases where the greedy algorithm can easily solve problems.

Problem: Coin Change

You are the shopkeeper, and you need to give the customer change in coins. The shop has the following coins available:

  • 500 won coin
  • 100 won coin
  • 50 won coin
  • 10 won coin

You want to use the optimal number of coins to give change to the customer. If the customer requests 1260 won in change, you can give the coins as follows:

  • 2 pieces – 500 won
  • 2 pieces – 100 won
  • 1 piece – 50 won
  • 1 piece – 10 won

In total, you will give out 6 coins. The input and output format of the program is as follows:

Input

First line: Amount of change to give N (1 <= N <= 10,000)

Output

Minimum number of coins

Problem Solving Process

1. Understanding the Problem

To solve the problem, we need to minimize the number of coins for the given amount. We approach the problem by starting with the highest denomination of coins and recalculating the remaining amount.

2. Algorithm Design

By applying the greedy algorithm, we proceed with the following steps:

  • Check the given amount N.
  • Sort the coin values from largest to smallest.
  • Use the value of each coin to reduce the amount.
  • Count the number of coins used each time a coin is used.
  • Repeat this process until the remaining amount is 0.

3. Code Implementation

Now, let’s write the JavaScript code to solve the problem.


function minCoins(N) {
    const coins = [500, 100, 50, 10]; // Coin values
    let count = 0; // Coin count

    for (let i = 0; i < coins.length; i++) {
        // Calculate how many of the current coin can be used by dividing by N
        count += Math.floor(N / coins[i]);
        // Subtract the used amount from N
        N %= coins[i]; 
    }
    
    return count;
}

// Example usage
const amount = 1260; // Requested change
console.log(`Minimum number of coins: ${minCoins(amount)}`); // Output: 6

4. Code Explanation

In the above code:

  • The minCoins function receives the change amount through the parameter N.
  • The coins array lists the coin values from largest to smallest.
  • Through a for loop, we check each coin value and calculate the number of usable coins using Math.floor(N / coins[i]).
  • After using the coin, the remaining amount is updated with N %= coins[i].
  • Finally, the total number of coins is returned.

5. Functionality Check

Now, we will run various test cases using the above code to check its functionality. Let’s test various inputs.


console.log(minCoins(5000)); // Output: 10
console.log(minCoins(1000)); // Output: 2
console.log(minCoins(560));  // Output: 2
console.log(minCoins(9999)); // Output: specific value

Conclusion

In this lesson, we solved the coin change problem using a greedy algorithm. The greedy algorithm is very useful for simple problems and helps solve various issues, such as coin problems or knapsack problems. Moving forward, try to solve various greedy algorithm problems to gain more experience.

JavaScript Coding Test Course, Checking the Intersection of Line Segments

Hello everyone! Today we will discuss one of the frequently encountered problems in JavaScript coding tests: ‘Determining if line segments intersect’. This problem is often asked in interviews and is very helpful in developing the ability to understand geometric concepts and implement them in code.

Problem Description

This problem is about determining whether two given line segments intersect. Each segment is defined by two points: segment A is represented by points A1(x1, y1) and A2(x2, y2), while segment B is represented by points B1(x3, y3) and B2(x4, y4). We need to determine whether these two segments intersect.

Input

  • A1: (x1, y1)
  • A2: (x2, y2)
  • B1: (x3, y3)
  • B2: (x4, y4)

Output

If they intersect, the output should be true; otherwise, it should return false.

Examples

Input Example

    A1: (1, 1), A2: (4, 4)
    B1: (1, 4), B2: (4, 1)
  

Output Example

    true
  

Approach to the Problem

To solve this problem, we need to utilize some geometric concepts and algorithms. We will introduce two methods to determine whether the line segments intersect. The first method uses the area of a polygon, while the second utilizes the concept of the cross product of vectors.

1. Determining intersection using the cross product

To determine if the segments intersect, we use the cross product of vectors. If the cross product of two direction vectors A and B is greater than 0, they are on one side; if less than 0, they are on the opposite side.

Equation of a line

    Let's define line segments A and B:
    A: [(x1, y1), (x2, y2)]
    B: [(x3, y3), (x4, y4)]
  

Cross product formula

The following cross product formula can be used for segments AB and AC:

    cross(A, B) = (A.x * B.y - A.y * B.x)
  

2. Determining intersection between a segment and a line

When given a segment, we can use another technique to determine if a specific line intersects the segment. This fundamentally involves reading the line defined by the endpoints of the segments and calculating the intersection.

Implementation Code

Now, let’s implement the actual code using the methods described above.


    function isIntersect(A1, A2, B1, B2) {
      const orientation = (p, q, r) => {
        const val = (q[1] - p[1]) * (r[0] - q[0]) - (q[0] - p[0]) * (r[1] - q[1]);
        if (val === 0) return 0; // collinear
        return (val > 0) ? 1 : 2; // clock or counterclockwise
      };
      
      const onSegment = (p, q, r) => {
        return (
          q[0] <= Math.max(p[0], r[0]) &&
          q[0] >= Math.min(p[0], r[0]) &&
          q[1] <= Math.max(p[1], r[1]) &&
          q[1] >= Math.min(p[1], r[1])
        );
      };
      
      const o1 = orientation(A1, A2, B1);
      const o2 = orientation(A1, A2, B2);
      const o3 = orientation(B1, B2, A1);
      const o4 = orientation(B1, B2, A2);
      
      if (o1 !== o2 && o3 !== o4) return true;
      if (o1 === 0 && onSegment(A1, B1, A2)) return true;
      if (o2 === 0 && onSegment(A1, B2, A2)) return true;
      if (o3 === 0 && onSegment(B1, A1, B2)) return true;
      if (o4 === 0 && onSegment(B1, A2, B2)) return true;

      return false;
    }

    // Example usage
    const A1 = [1, 1],
          A2 = [4, 4],
          B1 = [1, 4],
          B2 = [4, 1];

    console.log(isIntersect(A1, A2, B1, B2)); // true
  

Code Explanation

First, the orientation function determines the directionality of the three given points (p, q, r). This helps determine the intersection of segments A and B.

Next, the onSegment function checks if the point q lies on the segment pr. After confirming the intersection, further checks are performed for specific cases (when all three points coincide).

Time Complexity

The time complexity of this algorithm is O(1) since the intersection can be determined with just one comparison.

Conclusion

In this tutorial, we explored an algorithm to determine the intersection of line segments using JavaScript. I hope this helps enhance your understanding of geometric problems and coding skills. I wish you the best in your interview preparation, and I look forward to seeing you in the next lesson!

Javascript Coding Test Course, Interval Sum

Hello! In this tutorial, we will explore the “range sum” problem, which is frequently featured in JavaScript coding tests, in depth. The range sum problem involves efficiently calculating the sum of a specific range within a given sequence, and it can be solved using various optimization techniques. The range sum problems we will discuss can be particularly time-consuming when the size of the array is large, so it’s essential to design a more efficient algorithm.

Problem Introduction

Here is a problem related to range sums:

Problem Description

An array of integers arr and several pairs of integers (l, r) are given. Each pair represents the starting point l and endpoint r of a range. Write a program to calculate the sum of arr[l] + arr[l + 1] + ... + arr[r]. The length of the array and the number of pairs are as follows:

  • 1 ≤ arr.length ≤ 106
  • 1 ≤ l, rarr.length
  • 0 ≤ arr[i] ≤ 109

For example, if the array is arr = [1, 2, 3, 4, 5] and the pair (1, 3) is given, the range sum is arr[1] + arr[2] + arr[3] = 2 + 3 + 4 = 9.

Approach to the Problem

To solve this problem efficiently, simply using loops to calculate the sum for each range is not appropriate. The reason is that in the worst-case scenario, it would have a time complexity of O(N * M), which can lead to exponential time increases if the size of the data is large. Instead, we can use a more effective approach.

Preprocessing Technique: Prefix Sum Array

One way to solve the range sum problem is to create a Prefix Sum Array. Using a prefix sum array allows us to calculate the sum of a range in O(1) time. The definition of the prefix sum array is as follows:

prefix[i] = arr[0] + arr[1] + ... + arr[i-1]

Thus, the sum of the range (l, r) can be calculated as:

sum(l, r) = prefix[r + 1] - prefix[l]

This allows us to compute the range sum for each pair in O(1) time. The overall time complexity of the algorithm is O(N + M), where N is the size of the array and M is the number of pairs.

Implementation Steps

Now, let’s implement the JavaScript code that solves the problem using the prefix sum array.

Step 1: Create the Prefix Sum Array


function createPrefixSum(arr) {
    const prefix = new Array(arr.length + 1).fill(0);
    for (let i = 0; i < arr.length; i++) {
        prefix[i + 1] = prefix[i] + arr[i];
    }
    return prefix;
}

Step 2: Calculate the Range Sum


function rangeSum(prefix, l, r) {
    return prefix[r + 1] - prefix[l];
}

Step 3: Implement the Main Function


function calculateRangeSums(arr, queries) {
    const prefix = createPrefixSum(arr);
    const results = [];
    for (let [l, r] of queries) {
        results.push(rangeSum(prefix, l - 1, r - 1)); // 1-based to 0-based
    }
    return results;
}

// Example usage
const arr = [1, 2, 3, 4, 5];
const queries = [[1, 3], [2, 5], [0, 2]];
const results = calculateRangeSums(arr, queries);
console.log(results); // [9, 14, 6]

Results Analysis

The above code is a program that efficiently calculates and outputs the range sum for each query based on the given array and queries. As a result, it can quickly compute range sums and does not suffer performance degradation depending on the size of the array or the number of queries.

Time Complexity

The time complexity of this algorithm is as follows:

  • Creating the prefix sum array: O(N)
  • Processing each query: O(1) (If you combine processing all M queries, it becomes O(M))

As a result, the overall time complexity is O(N + M), which is very efficient.

Conclusion

Now we have learned how to efficiently solve the range sum problem using a prefix sum array. Since range sum problems are frequently featured topics in coding tests, understanding and utilizing optimization techniques like this is important. Practice solving various types of problems!

Additional Practice Problems

Try practicing the following variant problems:

  • Problems that find the maximum value of the range instead of the sum
  • Problems that find the product of the range (note that division operations may need to be considered)
  • Consider how to handle different queries (e.g., range increment, decrement, etc.)

Based on the above content, I hope you solve various problems. Thank you!

JavaScript Coding Test Course, Queue Management

Problem Description

There is height information for a group of students. You need to specify one student among them
and arrange the line so that this student stands at the front.
In this case, students shorter than the specified student must stand behind, and
the order of students with the same height must remain unchanged.
Write an algorithm that satisfies these conditions for lining up the students.

Input Format

    An array containing the heights of students (e.g., [160, 170, 165, 180, 175])
    Height of the specified student (e.g., 170)
    

Output Format

    An array of the lined-up students' heights (e.g., [170, 160, 165, 180, 175])
    

Problem Solving Process

Step 1: Understand the Problem

The crux of the problem is to place the specified height student at the front of the given array, while
sorting the remaining students by height, maintaining their original order. This problem can primarily be solved using stable sorting.
The algorithm we will implement includes the following steps.

Step 2: Analyze a Simple Example

For example, if the input is [160, 170, 165, 180, 175] and 170,
the lined-up result should be [170, 160, 165, 180, 175]. The key point to note is
that when multiple students have the same height, their order must be preserved.

Step 3: Develop a Solution Strategy

The solution method is as follows.

  1. Find the student with the specified height in the given array and add that student as the first element of the result array.
  2. Add the remaining students to the result array while maintaining their original order, excluding students with the same height.
  3. Finally, return the modified array.

Step 4: Implement JavaScript Code

Based on the above strategy, I will write a JavaScript function. This function will take two parameters and
serve to move the specified height student to the front.

function lineUpStudents(students, targetHeight) {
    // Declare an array to store the result
    let result = [];

    // First, add the student corresponding to targetHeight
    const targetStudents = students.filter(height => height === targetHeight);
    result.push(...targetStudents);

    // Add the remaining students (maintaining original order)
    const otherStudents = students.filter(height => height !== targetHeight);
    result.push(...otherStudents);

    return result;
}
        

Step 5: Test and Validate the Code

I will run a few test cases to confirm that the function works correctly.

console.log(lineUpStudents([160, 170, 165, 180, 175], 170)); // [170, 160, 165, 180, 175]
console.log(lineUpStudents([160, 160, 165, 170, 180], 160)); // [160, 160, 165, 170, 180]
console.log(lineUpStudents([180, 170, 160, 150], 160)); // [160, 180, 170, 150]
        

Step 6: Complexity Analysis

The time complexity of this algorithm is O(n). This is because we iterate through the given array once.
The space complexity is also O(n) since a separate result array is created.

Conclusion

In this tutorial, we learned how to solve the problem of lining up students based on their height information
using JavaScript.
Maintaining a stable sort by height was the key to this problem.
Such problems are very important as they frequently appear in coding tests.
Practicing various variations of this problem can also be good preparation for developing algorithmic thinking.