Solve array and tree algorithm challenges
Company: TikTok
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: Medium
Interview Round: Technical Screen
Quick Answer: This question evaluates algorithmic problem-solving skills across array, heap, and tree data structures, testing competencies in duplicate handling, frequency aggregation, and balancing root-to-leaf path sums within the Coding & Algorithms domain.
Unique Triplet Sum (3Sum)
Constraints
- 0 <= len(nums) <= 3000
- -10^5 <= nums[i] <= 10^5
- target defaults to 0 if not provided
- Each triplet in the output must be unique (no duplicate [a, b, c] sets)
Examples
Input: ([-1, 0, 1, 2, -1, -4], 0)
Expected Output: [[-1, -1, 2], [-1, 0, 1]]
Explanation: Two distinct triplets sum to 0; the duplicate -1 is handled so [-1,0,1] appears once.
Input: ([0, 0, 0, 0], 0)
Expected Output: [[0, 0, 0]]
Explanation: All zeros yield a single unique triplet despite four zeros.
Input: ([1, 2, 3], 100)
Expected Output: []
Explanation: No triplet reaches the target.
Input: ([], 0)
Expected Output: []
Explanation: Empty input returns an empty list.
Input: ([-2, 0, 1, 1, 2], 0)
Expected Output: [[-2, 0, 2], [-2, 1, 1]]
Explanation: Duplicate 1s produce the valid triplet [-2,1,1] exactly once.
Input: ([3, -2, 1, 0, -1, 2, -3], 1)
Expected Output: [[-3, 1, 3], [-2, 0, 3], [-2, 1, 2], [-1, 0, 2]]
Explanation: Non-zero target; four unique triplets sum to 1, listed in sorted-scan order.
Hints
- Sort the array first so equal values are adjacent — this makes both duplicate-skipping and the two-pointer scan possible.
- Fix the first element with an outer loop, then use a left/right two-pointer scan on the remaining suffix to find the other two values.
- After fixing index i, skip it when nums[i] == nums[i-1]; after recording a hit, advance past equal lo/hi values to avoid duplicate triplets.
K Most Common Values
Constraints
- 0 <= len(nums) <= 10^5
- -10^9 <= nums[i] <= 10^9
- 0 <= k <= number of distinct values in nums
- Frequency ties are broken by value descending; final output is sorted by frequency descending, then value descending
Examples
Input: ([1, 1, 1, 2, 2, 3], 2)
Expected Output: [1, 2]
Explanation: 1 (freq 3) then 2 (freq 2) are the two most common.
Input: ([1], 1)
Expected Output: [1]
Explanation: Single element.
Input: ([4, 4, 5, 5, 6], 2)
Expected Output: [5, 4]
Explanation: 4 and 5 tie at frequency 2; the tie is broken by value descending so 5 comes first.
Input: ([7, 7, 8, 8, 9, 9], 3)
Expected Output: [9, 8, 7]
Explanation: All three values tie at frequency 2, so output is purely value descending.
Input: ([], 3)
Expected Output: []
Explanation: Empty input returns empty.
Input: ([10, 20, 30], 0)
Expected Output: []
Explanation: k = 0 returns nothing.
Input: ([-1, -1, -2, -2, -3], 2)
Expected Output: [-1, -2]
Explanation: -1 and -2 tie at frequency 2; -1 > -2 so it comes first.
Input: ([5, 5, 5, 1, 1, 9], 2)
Expected Output: [5, 1]
Explanation: 5 (freq 3) and 1 (freq 2) win; 9 (freq 1) is excluded.
Hints
- Count frequencies first with a hash map / Counter.
- Keying the size-k min-heap by the tuple (frequency, value) lets a single pop evict the worst candidate AND break frequency ties toward the smaller value.
- A min-heap pops smallest-first, so to get descending output you sort the surviving k entries by (freq, value) in reverse at the end.
Equalize Root-to-Leaf Path Sums with Minimal Increments
Constraints
- 0 <= len(costs); the tree is a complete (perfect) binary tree, so len(costs) is typically 2^h - 1
- 0 <= costs[i] <= 10^4
- Only increments (cost + 1) are allowed; you may never decrease a cost
- Goal: all root-to-leaf path sums become equal with the fewest total increments
Examples
Input: ([0, 0, 0, 0, 0, 0, 0],)
Expected Output: 0
Explanation: All zeros, all paths already sum to 0.
Input: ([0, 0, 0, 0, 0, 1, 1],)
Expected Output: 1
Explanation: Right subtree's leaves are both 1 (already equal); root must lift its left child path (0) to match the right child path (1), costing 1.
Input: ([5],)
Expected Output: 0
Explanation: Single node is the only path; nothing to equalize.
Input: ([1, 1, 1],)
Expected Output: 0
Explanation: Both leaves already equal.
Input: ([1, 2, 3],)
Expected Output: 1
Explanation: Leaves 2 and 3 differ by 1; raise the 2-leaf to 3.
Input: ([10, 1, 5, 0, 0, 0, 0],)
Expected Output: 4
Explanation: Each child subtree is internally balanced (leaves all 0); root must lift the left child path (1) to match the right child path (5), costing 4.
Input: ([],)
Expected Output: 0
Explanation: Empty tree needs no increments.
Input: ([0, 0, 0, 1, 2, 3, 4],)
Expected Output: 4
Explanation: Left subtree: lift leaf 1 to 2 (cost 1). Right subtree: lift leaf 3 to 4 (cost 1). Then root lifts left path (2) to right path (4) (cost 2). Total 4.
Hints
- Think bottom-up: a node's two subtrees must end up with equal path sums before you can reason about the node above it.
- At each internal node the only optimal move is to raise the lighter child subtree's path sum up to the heavier one — the gap (max - left) + (max - right) is the increments charged at that node.
- Carry up costs[i] + max(left_child_sum, right_child_sum) as the node's own equalized path sum, and accumulate all the gaps as you ascend.