Apply Operations to an Array solution and explanation
9 more videos on this problem
Apply Operations to an Array - Leetcode 2460 - PythonNeetCodeIO · 8:30 · 6K views
Apply Operations to an Array | Leetcode 2460Techdose · 8:33 · 2K views
2460. Apply Operations to an Array | leetcode daily challenge | faang | shashcodeShashCode · 9:54 · 1K views
2460. Apply Operations to an Array | LEETCODE EASYcode Explainer · 8:06 · 1K views
Leetcode | 2460. Apply Operations to an Array | Easy | Java SolutionDeveloper Docs · 6:52 · 583 views
2460. Apply Operations to an Array (Leetcode Easy)Programming Live with Larry · 3:32 · 436 views
Apply Operations to an Array | Leetcode 2460Leetcode Guardian · 3:03 · 435 views
Leetcode 2460. Apply Operations to an ArrayElite Code · 9:42 · 220 views
LeetCode 2460 Apply Operations to an Array | Two Pointers | Asked in AmazonCode Harmony · 8:19 · 188 views
LeetCode 2460 | Apply Operations to an Array | JavaSleepy Cracker · 4:55 · 149 views
The problem
You are given a 0-indexed array nums of size n consisting of non-negative integers.
You need to apply n - 1 operations to this array where, in the ith operation (0-indexed), you will apply the following on the ith element of nums:
- If
nums[i] == nums[i + 1], then multiplynums[i]by2and setnums[i + 1]to0. Otherwise, you skip this operation.
After performing all the operations, shift all the 0's to the end of the array.
- For example, the array
[1,0,2,0,0,1]after shifting all its0's to the end, is[1,2,1,0,0,0].
Return the resulting array.
Note that the operations are applied sequentially, not all at once.
Example 1:
Input: nums = [1,2,2,1,1,0] Output: [1,4,2,0,0,0] Explanation: We do the following operations: - i = 0: nums[0] and nums[1] are not equal, so we skip this operation. - i = 1: nums[1] and nums[2] are equal, we multiply nums[1] by 2 and change nums[2] to 0. The array becomes [1,4,0,1,1,0]. - i = 2: nums[2] and nums[3] are not equal, so we skip this operation. - i = 3: nums[3] and nums[4] are equal, we multiply nums[3] by 2 and change nums[4] to 0. The array becomes [1,4,0,2,0,0]. - i = 4: nums[4] and nums[5] are equal, we multiply nums[4] by 2 and change nums[5] to 0. The array becomes [1,4,0,2,0,0]. After that, we shift the 0's to the end, which gives the array [1,4,2,0,0,0].
Example 2:
Input: nums = [0,1] Output: [1,0] Explanation: No operation can be applied, we just shift the 0 to the end.
Constraints:
2 <= nums.length <= 20000 <= nums[i] <= 1000
Approach overview
Problem Overview: You receive an integer array. First, scan left to right and apply a rule: if nums[i] == nums[i+1], double nums[i] and set nums[i+1] to zero. After completing this pass, move all zeros to the end while keeping the relative order of non‑zero elements. The result is the transformed array.
Approach 1: In-Place Modification with Zero Collection (Time: O(n), Space: O(n))
This method directly simulates the problem statement. Iterate through the array once and apply the merge rule: whenever two adjacent values are equal, update nums[i] to 2 * nums[i] and set nums[i+1] to zero. After this pass, build a new result by collecting all non-zero elements in order and appending the required number of zeros at the end. The key insight is separating the two phases: first apply the operation exactly as described, then perform a stable zero shift. This approach is easy to reason about and mirrors the problem statement, making it a solid baseline implementation using a simple array traversal and simulation.
Approach 2: Two-Pointer Technique for Zero Shift (Time: O(n), Space: O(1))
After applying the merge operation in a single left‑to‑right pass, shift non-zero values forward using the two pointers pattern. Maintain a write pointer that marks where the next non-zero element should go. Scan the array with another pointer. When a non-zero value appears, write it at the write index and advance the pointer. After processing all elements, fill the remaining positions with zeros. This avoids creating a new array and keeps the algorithm fully in-place. The insight is that the second phase is identical to the classic “move zeros to the end” problem.
Recommended for interviews: The two-pointer approach is typically preferred. It keeps the algorithm linear at O(n) time while using O(1) extra space. Showing the straightforward simulation first demonstrates that you understand the problem mechanics. Following it with the in-place two-pointer optimization shows stronger algorithmic thinking and familiarity with common array patterns.
Approach 1: In-Place Modification with Zero Collection
This approach involves iterating through the array and applying operations only when an element is equal to the next one. After completing all operations, traverse the array again to collect non-zero elements, thus effectively moving all zeros to the end.
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
result = [num for num in nums if num != 0]
result.extend([0] * (n - len(result)))
return result
# Example usage:
nums = [1, 2, 2, 1, 1, 0]
print(apply_operations(nums)) # Output: [1, 4, 2, 0, 0, 0]import java.util.ArrayList;
import java.util.List;
public class Main {
public static 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;
}
}
List<Integer> result = new ArrayList<>();
for (int num : nums) {
if (num != 0) {
result.add(num);
}
}
while (result.size() < n) {
result.add(0);
}
return result.stream().mapToInt(i -> i).toArray();
}
public static void main(String[] args) {
int[] nums = {1, 2, 2, 1, 1, 0};
int[] result = applyOperations(nums);
for (int num : result) {
System.out.print(num + " ");
}
}
}#include <iostream>
#include <vector>
using namespace std;
vector<int> applyOperations(vector<int>& nums) {
int n = nums.size();
for (int i = 0; i < n - 1; i++) {
if (nums[i] == nums[i + 1]) {
nums[i] *= 2;
nums[i + 1] = 0;
}
}
vector<int> result;
for (int num : nums) {
if (num != 0) {
result.push_back(num);
}
}
result.resize(n, 0);
return result;
}
int main() {
vector<int> nums = {1, 2, 2, 1, 1, 0};
vector<int> result = applyOperations(nums);
for (int num : result) {
cout << num << " ";
}
return 0;
}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;
}
}
const result = nums.filter(num => num !== 0);
while (result.length < n) {
result.push(0);
}
return result;
}
const nums = [1, 2, 2, 1, 1, 0];
console.log(applyOperations(nums)); // Output: [1, 4, 2, 0, 0, 0]#include <stdio.h>
void applyOperations(int nums[], int n) {
for (int i = 0; i < n - 1; i++) {
if (nums[i] == nums[i + 1]) {
nums[i] *= 2;
nums[i + 1] = 0;
}
}
int index = 0;
for (int i = 0; i < n; i++) {
if (nums[i] != 0) {
nums[index++] = nums[i];
}
}
while (index < n) {
nums[index++] = 0;
}
}
int main() {
int nums[] = {1, 2, 2, 1, 1, 0};
int n = sizeof(nums) / sizeof(nums[0]);
applyOperations(nums, n);
for (int i = 0; i < n; i++) {
printf("%d ", nums[i]);
}
return 0;
}using System;
using System.Collections.Generic;
public class Solution {
public static 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;
}
}
List<int> result = new List<int>();
foreach (int num in nums) {
if (num != 0) {
result.Add(num);
}
}
while (result.Count < n) {
result.Add(0);
}
return result.ToArray();
}
public static void Main() {
int[] nums = {1, 2, 2, 1, 1, 0};
int[] result = ApplyOperations(nums);
Console.WriteLine(string.Join(" ", result));
}
}The function first iterates through the array to apply the given operations: whenever nums[i] == nums[i+1], it multiplies nums[i] by 2 and sets nums[i+1] to zero. Then, it creates a new list of non-zero elements and appends the appropriate number of zeros to the end.
Time complexity is O(n), as we iterate through the array twice, which is efficient given the constraints. Space complexity is O(n) due to the construction of the result array, which is necessary to shift zeros to the end.
Approach 2: Two-Pointer Technique for Zero Shift
This alternative employs a two-pointer technique whereby one pointer processes operational changes and another places non-zero values, thereby compactly reordering elements without needing an auxiliary array.
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
write_position = 0
for i in range(n):
if nums[i] != 0:
nums[write_position] = nums[i]
write_position += 1
for i in range(write_position, n):
nums[i] = 0
return nums
# Example usage:
nums = [1, 2, 2, 1, 1, 0]
print(apply_operations(nums)) # Output: [1, 4, 2, 0, 0, 0]public class Main {
public static void 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 write_position = 0;
for (int i = 0; i < n; i++) {
if (nums[i] != 0) {
nums[write_position++] = nums[i];
}
}
for (int i = write_position; i < n; i++) {
nums[i] = 0;
}
}
public static void main(String[] args) {
int[] nums = {1, 2, 2, 1, 1, 0};
applyOperations(nums);
for (int num : nums) {
System.out.print(num + " ");
}
}
}#include <iostream>
#include <vector>
using namespace std;
void applyOperations(vector<int>& nums) {
int n = nums.size();
for (int i = 0; i < n - 1; i++) {
if (nums[i] == nums[i + 1]) {
nums[i] *= 2;
nums[i + 1] = 0;
}
}
int write_position = 0;
for (int i = 0; i < n; i++) {
if (nums[i] != 0) {
nums[write_position++] = nums[i];
}
}
for (int i = write_position; i < n; i++) {
nums[i] = 0;
}
}
int main() {
vector<int> nums = {1, 2, 2, 1, 1, 0};
applyOperations(nums);
for (int num : nums) {
cout << num << " ";
}
return 0;
}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 write_position = 0;
for (let i = 0; i < n; i++) {
if (nums[i] !== 0) {
nums[write_position++] = nums[i];
}
}
for (let i = write_position; i < n; i++) {
nums[i] = 0;
}
}
const nums = [1, 2, 2, 1, 1, 0];
applyOperations(nums);
console.log(nums); // Output: [1, 4, 2, 0, 0, 0]#include <stdio.h>
void applyOperations(int nums[], int n) {
for (int i = 0; i < n - 1; i++) {
if (nums[i] == nums[i + 1]) {
nums[i] *= 2;
nums[i + 1] = 0;
}
}
int write_position = 0;
for (int i = 0; i < n; i++) {
if (nums[i] != 0) {
nums[write_position++] = nums[i];
}
}
for (int i = write_position; i < n; i++) {
nums[i] = 0;
}
}
int main() {
int nums[] = {1, 2, 2, 1, 1, 0};
int n = sizeof(nums) / sizeof(nums[0]);
applyOperations(nums, n);
for (int i = 0; i < n; i++) {
printf("%d ", nums[i]);
}
return 0;
}using System;
public class Solution {
public static void 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 write_position = 0;
foreach (int num in nums) {
if (num != 0) {
nums[write_position++] = num;
}
}
for (int i = write_position; i < n; i++) {
nums[i] = 0;
}
}
public static void Main() {
int[] nums = {1, 2, 2, 1, 1, 0};
ApplyOperations(nums);
Console.WriteLine(string.Join(" ", nums));
}
}Utilizing a write_position, this method writes non-zero elements to the front, efficiently shifting zeros to the end. This guarantees minimum in-place changes, effectively combining both stages of operation and zero positioning.
Time complexity remains O(n) as the list is traversed twice; space complexity is constant, O(1), as no extra data structures are used besides a few pointers.
Approach 3: Simulation
We can directly simulate according to the problem description.
First, we traverse the array nums. For any two adjacent elements nums[i] and nums[i+1], if nums[i] = nums[i+1], then we double the value of nums[i] and change the value of nums[i+1] to 0.
Then, we create an answer array ans of length n, and put all non-zero elements of nums into ans in order.
Finally, we return the answer array ans.
The time complexity is O(n), where n is the length of the array nums. Ignoring the space consumption of the answer, the space complexity is O(1).
function applyOperations(nums: number[]): number[] {
const n = nums.length;
for (let i = 0; i < n - 1; ++i) {
if (nums[i] === nums[i + 1]) {
nums[i] <<= 1;
nums[i + 1] = 0;
}
}
const ans: number[] = Array(n).fill(0);
let i = 0;
for (const x of nums) {
if (x !== 0) {
ans[i++] = x;
}
}
return ans;
}func applyOperations(nums []int) []int {
n := len(nums)
for i := 0; i < n-1; i++ {
if nums[i] == nums[i+1] {
nums[i] <<= 1
nums[i+1] = 0
}
}
ans := make([]int, n)
i := 0
for _, x := range nums {
if x > 0 {
ans[i] = x
i++
}
}
return ans
}impl Solution {
pub fn apply_operations(nums: Vec<i32>) -> Vec<i32> {
let mut nums = nums;
for i in 0..nums.len() - 1 {
if nums[i] == nums[i + 1] {
nums[i] <<= 1;
nums[i + 1] = 0;
}
}
let mut cur = 0;
for i in 0..nums.len() {
if nums[i] != 0 {
nums.swap(i, cur);
cur += 1;
}
}
nums
}
}Complexity comparison
| Approach | Complexity |
|---|---|
| In-Place Modification with Zero Collection | Time complexity is O(n), as we iterate through the array twice, which is efficient given the constraints. Space complexity is O(n) due to the construction of the result array, which is necessary to shift zeros to the end. |
| Two-Pointer Technique for Zero Shift | Time complexity remains O(n) as the list is traversed twice; space complexity is constant, O(1), as no extra data structures are used besides a few pointers. |
| Simulation | – |
Complexity analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| In-Place Modification with Zero Collection | O(n) | O(n) | When clarity is more important than memory usage; mirrors the problem statement directly |
| Two-Pointer Technique for Zero Shift | O(n) | O(1) | Preferred for interviews and production when memory usage must stay constant |
Frequently asked questions
Is Apply Operations to an Array easy or hard?
Apply Operations to an Array is classified as an Easy problem on LeetCode with an acceptance rate around 74%. It mainly tests careful array traversal, simulation logic, and familiarity with the two-pointer pattern.
Apply Operations to an Array Python/Java solution
Both Python and Java implementations follow the same logic: iterate once to apply merge operations and then shift non-zero elements using a pointer that tracks the next write position. The algorithm remains O(n) time and O(1) extra space.
How to solve Apply Operations to an Array in O(n)?
Iterate through the array and merge equal adjacent values by doubling the left value and setting the right value to zero. After this pass, use a two-pointer technique to move non-zero elements forward and fill the rest of the array with zeros. Both steps are linear scans, giving O(n) time complexity.
What is the best approach for Apply Operations to an Array?
The two-pointer approach is the most efficient solution. First apply the merge rule in a single pass, then move non-zero values forward using a write pointer. This keeps the algorithm O(n) time with O(1) extra space while preserving the order of elements.
Is Apply Operations to an Array asked at Google/Amazon/Meta?
Problems like this frequently appear in screening rounds at companies such as Amazon and Google because they test array manipulation and pointer techniques. The pattern of merging elements and shifting zeros is a common interview variation.
What data structure is used in Apply Operations to an Array?
The problem primarily uses arrays. The optimized solution also relies on the two-pointer technique to rearrange elements in place without additional data structures.
What is the time complexity of Apply Operations to an Array?
The optimal solution runs in O(n) time because the array is scanned a constant number of times. One pass applies the merge operations and another pass shifts non-zero elements forward. Each element is processed only a few times.
