kotlin coding test course, ‘Finding Good Numbers’

Hello! In this session, we will solve one of the coding test problems using Kotlin, which is to find a ‘good number’. In this article, I will explain the problem description, approach, algorithm design, and actual code step by step. We will also cover various examples along with optimization, so please stay with us until the end!

Problem Description

A ‘good number’ problem is to find the combinations of different numbers (A, B, C, …) from a given list of integers such that A + B + C = 0. For example, suppose we have the following array.

 [-1, 0, 1, 2, -1, -4] 

The combinations of numbers that sum to 0 in the above array are (-1, 0, 1) and (-1, -1, 2). We must find and return all such combinations.

Approach to the Problem

To solve this problem, we need to consider a few basic approaches.

  1. Sorting: By sorting the array, we can effectively handle the same numbers and apply algorithms such as the two-pointer technique or binary search.
  2. Duplicate Removal: We need to ensure that the same number is not added multiple times.
  3. Pointer Technique: Using two pointers based on the sorted list allows us to efficiently check each combination.

Algorithm Design

The algorithm consists of the following steps.

  1. Sort the input array.
  2. Then, for each element, use two pointers to check if the sum equals 0.
  3. Avoid duplicates when adding to the result list.

Code Implementation

Now, let’s implement the code. We will write it in Kotlin as follows:


        fun threeSum(nums: IntArray): List> {
            nums.sort() // Sort the array
            val res = mutableListOf>()
            for (i in nums.indices) {
                if (i > 0 && nums[i] == nums[i - 1]) continue // Check for duplicates
                var left = i + 1
                var right = nums.size - 1
                while (left < right) {
                    val sum = nums[i] + nums[left] + nums[right]
                    when {
                        sum < 0 -> left++      // Move left pointer if sum is less
                        sum > 0 -> right--     // Move right pointer if sum is greater
                        else -> {
                            res.add(listOf(nums[i], nums[left], nums[right])) // Add when sum is 0
                            while (left < right && nums[left] == nums[left + 1]) left++ // Check for duplicates
                            while (left < right && nums[right] == nums[right - 1]) right-- // Check for duplicates
                            left++
                            right--
                        }
                    }
                }
            }
            return res
        }
        

Code Analysis

Let's analyze each part of the code.

  1. Array Sorting: The array is sorted in ascending order using `nums.sort()`. This is a prerequisite for applying the two-pointer technique.
  2. Main Loop: We iterate based on the index, selecting each element. If there's a duplicate, we skip it.
  3. Two Pointers: Based on the selected element, left and right pointers are set. We calculate and compare the sum of the three elements while moving these pointers.

Optimization and Time Complexity

The time complexity of this algorithm is O(n^2). This is because the outer loop runs n times and the inner while loop can run up to n times. Therefore, as the size of the list increases, the time complexity can increase significantly, requiring efficient handling.

The space complexity is O(1), as no additional space is used other than the input. However, space is used to store the result list.

Examples and Output

I will help clarify with example input and output.


        val input = intArrayOf(-1, 0, 1, 2, -1, -4)
        val result = threeSum(input)
        println(result) // Output: [[-1, -1, 2], [-1, 0, 1]]
        

Conclusion

In this lecture, we explored the process of designing and implementing an algorithm to find a ‘good number’ using Kotlin. By utilizing sorting, duplicate checking, and the two-pointer technique, we effectively solved the problem. I hope this helps improve your algorithmic thinking and coding skills as you tackle similar problems.

In the future, take time to explore multiple solutions through various algorithm problems!