Sum of Imbalance Numbers of All Subarrays — Solution
Sum of Imbalance Numbers of All Subarrays solution explained: step-by-step approach, complexity and code in Python, Java, C++ and JavaScript. A hard problem.
Sum of Imbalance Numbers of All Subarrays is a hard coding problem on arrays, hash table and ordered set, asked in Google interviews.
- Difficulty: Hard
- Topics: Arrays, Hash Table, Ordered Set
- Asked at: Google
- Time limit: 2 s
- Memory limit: 256 MB
- Languages: JavaScript, TypeScript, Python, Java, C++, C, C#, Go, Kotlin, Swift, Rust, PHP and Ruby
Problem statement
The imbalance number of an array arr is the number of indices i (0 <= i < n - 1) of sarr = sorted(arr) for which sarr[i + 1] - sarr[i] > 1 — the number of gaps between neighbouring values once the array is sorted.
Given an integer array nums, return the sum of the imbalance numbers of all its non-empty contiguous subarrays.
Example 1
Input: nums = [2,3,1,4]
Output: 3
Explanation: Only `[3,1]`, `[3,1,4]` and `[1,4]` have a gap (each exactly one); every other subarray sorts into consecutive values.
Example 2
Input: nums = [1,3,3,3,5]
Output: 8
Explanation: Subarrays such as `[1,3,3,3,5]` sort to `[1,3,3,3,5]` with two gaps; equal values never form a gap.
Example 3
Input: nums = [1]
Output: 0
Constraints
1 <= nums.length <= 10001 <= nums[i] <= nums.length
Hints for Sum of Imbalance Numbers of All Subarrays
Hint 1
Sorting every subarray is far too slow. Fix the left end and grow the subarray one element at a time — can you update the imbalance in O(1) per step?
Hint 2
Think of the distinct values present as maximal runs of consecutive integers. The imbalance is exactly (number of runs) − 1.
Hint 3
Adding a value
xthat is already present changes nothing. A newxstarts a run, but merges with the run ofx - 1if present and with the run ofx + 1if present — each merge removes one run.
How to solve Sum of Imbalance Numbers of All Subarrays
The sorted distinct values of a subarray split into maximal runs of consecutive integers, and each boundary between two runs is one gap — so imbalance = runs − 1. Runs can be maintained in O(1) as a subarray grows to the right, with a seen array over the small value range.
Approach
- For each left end
i, clear a boolean arrayseenof sizen + 2and setruns = 0. - Extend the right end
jfromi. Letx = nums[j]. Ifseen[x]is already set, the runs are unchanged. - Otherwise mark it and set
runs += 1, thenruns -= 1ifseen[x - 1], andruns -= 1ifseen[x + 1]. - Add
runs - 1to the answer for the subarraynums[i..j].
Why it works
Duplicates never create a gap, so only the set of distinct values matters. That set is a union of maximal blocks of consecutive integers; sorted, consecutive blocks are separated by exactly one difference greater than 1, and inside a block every difference is 1 — hence imbalance = blocks − 1. A new value x is a block on its own unless x - 1 or x + 1 is present, in which case it glues onto (or bridges) those blocks, each neighbour reducing the count by one.
Complexity
- Time —
O(n^2) - Space —
O(n)
Pitfalls
- A repeated value must not change the run count — check
seen[x]first. - Index
x + 1can ben + 1, so size the arrayn + 2. - The imbalance of a single-element subarray is 0 (one run), not −1 — the formula runs − 1 already gives 0 because there is always at least one run.
Reference solution
Python
from typing import List
def sumImbalanceNumbers(nums: List[int]) -> int:
n = len(nums)
total = 0
for i in range(n):
seen = [False] * (n + 2)
runs = 0
for j in range(i, n):
x = nums[j]
if not seen[x]:
seen[x] = True
runs += 1
if seen[x - 1]:
runs -= 1
if seen[x + 1]:
runs -= 1
total += runs - 1
return totalJava
public static int sumImbalanceNumbers(int[] nums) {
int n = nums.length;
int total = 0;
for (int i = 0; i < n; i++) {
boolean[] seen = new boolean[n + 2];
int runs = 0;
for (int j = i; j < n; j++) {
int x = nums[j];
if (!seen[x]) {
seen[x] = true;
runs++;
if (seen[x - 1]) runs--;
if (seen[x + 1]) runs--;
}
total += runs - 1;
}
}
return total;
}C++
int sumImbalanceNumbers(vector<int>& nums) {
int n = nums.size();
int total = 0;
for (int i = 0; i < n; i++) {
vector<bool> seen(n + 2, false);
int runs = 0;
for (int j = i; j < n; j++) {
int x = nums[j];
if (!seen[x]) {
seen[x] = true;
runs++;
if (seen[x - 1]) runs--;
if (seen[x + 1]) runs--;
}
total += runs - 1;
}
}
return total;
}JavaScript
var sumImbalanceNumbers = function(nums) {
var n = nums.length;
var total = 0;
var seen = new Uint8Array(n + 2);
for (var i = 0; i < n; i++) {
seen.fill(0);
var runs = 0;
for (var j = i; j < n; j++) {
var x = nums[j];
if (!seen[x]) {
seen[x] = 1;
runs++;
if (seen[x - 1]) runs--;
if (seen[x + 1]) runs--;
}
total += runs - 1;
}
}
return total;
};Also on the editorial tab: C, C#, Go, Kotlin, PHP, Ruby, Rust, Swift, TypeScript.
All 1199 arrays problems · the whole catalogue
Learn the technique: Arrays · Hashing: Hash Maps and Hash Sets