#315
Count of Smaller Numbers After Self
HardArrayBinary SearchDivide and ConquerBinary Indexed TreeSegment TreeMerge SortOrdered SetMerge SortDivide and Conquer
Approaches
Brute ForceOptimal
Complexity Comparison
| Brute Force | Optimal Solution★ | |
|---|---|---|
| Time | O(n²) | O(n log n) |
| Space | O(1) | O(n) |
💡
Intuition
Time O(n log n)Space O(n)
Using a modified merge sort allows us to count smaller elements efficiently while sorting the array. This approach leverages the divide-and-conquer strategy to maintain order and count inversions.
⚙️
Algorithm
3 steps- 1Step 1: Create a helper function that performs merge sort and counts smaller elements.
- 2Step 2: During the merge step, count how many elements from the right half are smaller than elements from the left half.
- 3Step 3: Store the counts in an auxiliary array that corresponds to the original indices.
solution.py27 lines
1# Full working Python code
2
3def countSmaller(nums):
4 def merge_sort(enum):
5 if len(enum) <= 1:
6 return enum, [0] * len(enum)
7 mid = len(enum) // 2
8 left, left_counts = merge_sort(enum[:mid])
9 right, right_counts = merge_sort(enum[mid:])
10 merged = []
11 counts = [0] * len(enum)
12 j = 0
13 for i in range(len(left)):
14 while j < len(right) and right[j][0] < left[i][0]:
15 merged.append(right[j])
16 j += 1
17 counts[left[i][1]] += j
18 merged.append(left[i])
19 merged.extend(right[j:])
20 return merged, counts
21
22 indexed_nums = list(enumerate(nums))
23 _, counts = merge_sort(indexed_nums)
24 return counts
25
26# Example usage
27print(countSmaller([5, 2, 6, 1])) # Output: [2, 1, 1, 0]ℹ
Complexity note: This complexity is due to the merge sort process, which divides the array and merges it while counting smaller elements efficiently.
- 1Using sorting techniques can significantly reduce time complexity.
- 2Understanding how to count inversions during sorting is crucial.
Solutions and explanations are original Tejav content. Problem titles © LeetCode — use the LeetCode button above for the full problem statement.