Find K Closest Elements - Complete Solution Guide
Find K Closest Elements is LeetCode problem 658, a Medium level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
Given a sorted integer array arr , two integers k and x , return the k closest integers to x in the array. The result should also be sorted in ascending order. An integer a is closer to x than an integer b if: |a - x| < |b - x| , or |a - x| == |b - x| and a < b Example 1: Input: arr = [1,2,3,4,5], k = 4, x = 3 Output: [1,2,3,4] Example 2: Input: arr = [1,1,2,3,4,5], k = 4, x = -1 Output: [1,1,2,3] Constraints: 1 <= k <= arr.length 1 <= arr.length <= 10 4 arr is sorted in ascending order. -10 4 <
Detailed Explanation
The problem asks us to find the `k` integers in a sorted array `arr` that are closest to a given value `x`. Closeness is defined as having the smallest absolute difference with `x`. If two numbers have the same absolute difference with `x`, the smaller number is considered closer. The returned list of `k` closest elements must also be sorted in ascending order. The input includes a sorted array `arr`, an integer `k` representing the number of closest elements to find, and an integer `x` representing the target value.
Solution Approach
The solution uses a binary search algorithm to find the starting index of the subarray of size `k` that contains the `k` closest elements to `x`. The binary search operates on the possible starting indices of the subarray. In each iteration, it compares the distance between `x` and the element at the start of the current window (`arr[mid]`) with the distance between `x` and the element just after the current window (`arr[mid + k]`). This comparison determines whether the window should be shifted to the right or the left. Once the binary search converges to the correct starting index, the subarray of size `k` starting from that index is returned.
Step-by-Step Algorithm
- Step 1: Initialize `left` to 0 and `right` to `len(arr) - k`. `left` and `right` define the search space for the starting index of the k-element window.
- Step 2: Perform binary search while `left < right`.
- Step 3: Calculate the middle index `mid = (left + right) // 2`.
- Step 4: Compare `x - arr[mid]` with `arr[mid + k] - x`. This comparison determines if the window starting at `mid` is too far to the left or too far to the right.
- Step 5: If `x - arr[mid] > arr[mid + k] - x`, it means the current window is too far to the left. Shift the left boundary to `mid + 1` (`left = mid + 1`).
- Step 6: Otherwise, the current window is too far to the right, or it's the optimal window. Shift the right boundary to `mid` (`right = mid`).
- Step 7: After the binary search completes, `left` will be the starting index of the `k` closest elements. Return the subarray `arr[left:left + k]`.
Key Insights
- Insight 1: The input array is already sorted, allowing us to use binary search to efficiently find the starting index of the k closest elements.
- Insight 2: We don't need to compare individual elements with 'x'. Instead, we compare two 'windows' of size k. The comparison effectively identifies the region where the k closest elements reside.
- Insight 3: The comparison `x - arr[mid] > arr[mid + k] - x` is crucial for determining whether the 'optimal' window should be shifted to the right. This cleverly avoids having to compute and sort all differences.
Complexity Analysis
Time Complexity: O(log n)
Space Complexity: O(1)
Topics
This problem involves: Array, Two Pointers, Binary Search, Sliding Window, Sorting, Heap (Priority Queue).
Companies
Asked at: Atlassian, Coupang, DoorDash, LinkedIn, Yandex.