Watch 4 video solutions for Differences Between Two Objects, a medium level problem. This walkthrough by NeetCodeIO has 4,224 views views. Want to try solving it yourself? Practice on FleetCode or read the detailed text solution.
Write a function that accepts two deeply nested objects or arrays obj1 and obj2 and returns a new object representing their differences.
The function should compare the properties of the two objects and identify any changes. The returned object should only contains keys where the value is different from obj1 to obj2.
For each changed key, the value should be represented as an array [obj1 value, obj2 value]. Keys that exist in one object but not in the other should not be included in the returned object. The end result should be a deeply nested object where each leaf value is a difference array.
When comparing two arrays, the indices of the arrays are considered to be their keys.
You may assume that both objects are the output of JSON.parse.
Example 1:
Input:
obj1 = {}
obj2 = {
"a": 1,
"b": 2
}
Output: {}
Explanation: There were no modifications made to obj1. New keys "a" and "b" appear in obj2, but keys that are added or removed should be ignored.
Example 2:
Input:
obj1 = {
"a": 1,
"v": 3,
"x": [],
"z": {
"a": null
}
}
obj2 = {
"a": 2,
"v": 4,
"x": [],
"z": {
"a": 2
}
}
Output:
{
"a": [1, 2],
"v": [3, 4],
"z": {
"a": [null, 2]
}
}
Explanation: The keys "a", "v", and "z" all had changes applied. "a" was changed from 1 to 2. "v" was changed from 3 to 4. "z" had a change applied to a child object. "z.a" was changed from null to 2.
Example 3:
Input:
obj1 = {
"a": 5,
"v": 6,
"z": [1, 2, 4, [2, 5, 7]]
}
obj2 = {
"a": 5,
"v": 7,
"z": [1, 2, 3, [1]]
}
Output:
{
"v": [6, 7],
"z": {
"2": [4, 3],
"3": {
"0": [2, 1]
}
}
}
Explanation: In obj1 and obj2, the keys "v" and "z" have different assigned values. "a" is ignored because the value is unchanged. In the key "z", there is a nested array. Arrays are treated like objects where the indices are keys. There were two alterations to the the array: z[2] and z[3][0]. z[0] and z[1] were unchanged and thus not included. z[3][1] and z[3][2] were removed and thus not included.
Example 4:
Input:
obj1 = {
"a": {"b": 1},
}
obj2 = {
"a": [5],
}
Output:
{
"a": [{"b": 1}, [5]]
}
Explanation: The key "a" exists in both objects. Since the two associated values have different types, they are placed in the difference array.
Example 5:
Input:
obj1 = {
"a": [1, 2, {}],
"b": false
}
obj2 = {
"b": false,
"a": [1, 2, {}]
}
Output:
{}
Explanation: Apart from a different ordering of keys, the two objects are identical so an empty object is returned.
Constraints:
obj1 and obj2 are valid JSON objects or arrays2 <= JSON.stringify(obj1).length <= 1042 <= JSON.stringify(obj2).length <= 104Problem Overview: You receive two JSON-like objects obj1 and obj2. The task is to compute a deep difference object that highlights where the values differ. If two values are identical, they are ignored. If they differ, the result stores the pair [valueFromObj1, valueFromObj2]. Nested objects and arrays must be compared recursively.
Approach 1: JSON Serialization Comparison (O(n) time, O(n) space)
A straightforward idea is to serialize both structures using JSON.stringify() and compare them. If the serialized strings are equal, the objects are identical. If not, traverse each key and record differences. This approach relies on string comparisons and repeated serialization of nested values. While easy to implement, it becomes inefficient for large nested objects and may break if key order differs. It also doesn’t naturally produce a structured diff unless you still recurse through the object.
Approach 2: Recursive Deep Comparison (O(n) time, O(n) space)
The practical solution uses recursion to walk through both objects simultaneously. First check if the two values are strictly equal. If they are, return an empty result. If their types differ or either value is a primitive, return an array [obj1, obj2] indicating the difference. When both values are objects or arrays, iterate over the keys present in both structures and recursively compute the difference for each key.
If the recursive call returns a non‑empty result, store it under that key in the output object. Arrays are handled naturally because their indices behave like object keys. This recursive strategy ensures every nested level is compared exactly once, giving linear complexity relative to the total number of properties across both structures.
This pattern is a classic use of recursion combined with structured traversal of JavaScript objects. Each recursive call reduces the problem to smaller nested values, similar to a depth-first traversal seen in DFS-style object exploration.
Recommended for interviews: The recursive deep comparison approach is the expected solution. A brute-force serialization idea shows basic reasoning, but interviewers want to see structured traversal and recursive decomposition of nested objects. The optimal solution runs in O(n) time and cleanly handles arbitrary nesting.
| Approach | Time | Space | When to Use |
|---|---|---|---|
| JSON Serialization Comparison | O(n) | O(n) | Quick equality checks for small objects where deep diff structure is not critical |
| Recursive Deep Comparison | O(n) | O(n) | General case with nested objects or arrays; produces accurate structural differences |