Apply Operations to an Array
Problem
You are given a 0-indexed array nums of size n. Apply n − 1 operations in order, where the i-th operation looks at the pair at positions i and i + 1: if nums[i] equals nums[i + 1], double nums[i] and set nums[i + 1] to 0; otherwise leave the pair unchanged. After all operations, shift every 0 to the end of the array while keeping the relative order of the non-zero values, and return the result.
nums = [1, 2, 2, 1, 1, 0][1, 4, 2, 0, 0, 0]def apply_operations(nums):
n = len(nums)
for i in range(n - 1):
if nums[i] == nums[i + 1]:
nums[i] *= 2
nums[i + 1] = 0
j = 0
for x in nums:
if x != 0:
nums[j] = x
j += 1
while j < n:
nums[j] = 0
j += 1
return nums
function applyOperations(nums) {
const n = nums.length;
for (let i = 0; i < n - 1; i++) {
if (nums[i] === nums[i + 1]) {
nums[i] *= 2;
nums[i + 1] = 0;
}
}
let j = 0;
for (const x of nums) {
if (x !== 0) nums[j++] = x;
}
while (j < n) nums[j++] = 0;
return nums;
}
class Solution {
public int[] applyOperations(int[] nums) {
int n = nums.length;
for (int i = 0; i < n - 1; i++) {
if (nums[i] == nums[i + 1]) {
nums[i] *= 2;
nums[i + 1] = 0;
}
}
int j = 0;
for (int x : nums) {
if (x != 0) nums[j++] = x;
}
while (j < n) nums[j++] = 0;
return nums;
}
}
vector<int> applyOperations(vector<int>& nums) {
int n = (int)nums.size();
for (int i = 0; i < n - 1; i++) {
if (nums[i] == nums[i + 1]) {
nums[i] *= 2;
nums[i + 1] = 0;
}
}
int j = 0;
for (int x : nums) {
if (x != 0) nums[j++] = x;
}
while (j < n) nums[j++] = 0;
return nums;
}
Explanation
The problem reads like two small jobs glued together, so we solve it in two passes.
Pass 1 — merge equal neighbours. We walk the array from left to right with index i going from 0 up to n − 2. At each step we compare nums[i] with its right neighbour nums[i + 1]. If they are the same, we double the left one and zero out the right one. The order matters: because we always move left to right and only ever zero the right element, a freshly created value cannot accidentally merge again in the same pass.
For nums = [1, 2, 2, 1, 1, 0]: the pair at i = 1 (2 and 2) becomes 4 and 0, and the pair at i = 3 (1 and 1) becomes 2 and 0. After the pass the array is [1, 4, 0, 2, 0, 0].
Pass 2 — push zeros to the end. We keep a write pointer j that marks where the next non-zero value belongs. Scanning the array, every time we meet a non-zero value we copy it to position j and advance j. Once the scan finishes, positions from j onward are filled with zeros. This is the classic stable "move zeros" two-pointer trick, so the non-zero values keep their original order.
That turns [1, 4, 0, 2, 0, 0] into [1, 4, 2, 0, 0, 0], which is the answer. Both passes are a single sweep each, so the whole thing is linear time and uses no extra array.