Given an array arr[] of size n, the task is to find the final array by repeatedly performing the following operations from left to right and check, If two adjacent elements have opposite signs:
- Remove both elements and insert the element with the larger absolute value, along with its sign.
- If both elements have the same absolute value, remove both without inserting anything.
Examples:
Input: arr[] = [10, -5, -8, 2, -5]
Output: [10]
Explanation:
At Index 0 : Element 10 has positive sign.
At Index 1 : -5 has lesser absolute value than 10. Replace both of them with 10.
At Index 2 : -8 has lesser absolute value than 10. Replace both of them with 10.
At Index 3 : 2 has positive sign. So it will be in the array.
At Index 4 : -5 has greater absolute value than 2. Replace both of them with 5.
Now -5 has lesser absolute value than 10. Replace both of them with 10.Input: arr[] = [5, -5, -2, -10]
Output: [-2, -10]
Explanation: 1st and 2nd element gets discarded because both elements have same values but opposite sign. 3rd and 4th elements have same sign. So, both will be in the array.
Table of Content
[Naive Approach] Iterative Method - O(n^2) Time and O(1) Space
The idea is to repeatedly scan the array from left to right and resolve only the first adjacent opposite sign pair by keeping the element with larger absolute value or removing both if equal. After each modification, restart the scan from the beginning since new adjacent pairs may form. Continue this process until no more such pairs exist in the array.
Dry run for arr[] = [10, -5, -8, 2, -5]:
- For i = 0, elements 10 and -5 have opposite signs and |10| > |−5|, so keep 10, Array becomes [10, -8, 2, -5]
- For i = 0, elements 10 and -8 have opposite signs and |10| > |−8|, so keep 10, Array becomes [10, 2, -5]
- For i = 0, elements 10 and 2 have same sign, so move ahead
- For i = 1, elements 2 and -5 have opposite signs and |−5| > |2|, so keep -5, Array becomes [10, -5]
- For i = 0, elements 10 and -5 have opposite signs and |10| > |−5|, so keep 10, Array becomes [10]
- No more pairs exist, process stops
Final array is [10]
#include <iostream>
#include <vector>
using namespace std;
vector<int> reducePairs(vector<int>& arr) {
bool changed = true;
while (changed) {
changed = false;
vector<int> temp;
for (int i = 0; i < arr.size(); i++) {
// check next element exists and signs are opposite
if (i + 1 < arr.size() && arr[i] * arr[i + 1] < 0) {
int a = arr[i], b = arr[i + 1];
if (abs(a) > abs(b)) {
temp.push_back(a);
}
else if (abs(a) < abs(b)) {
temp.push_back(b);
}
// if equal, both removed (do nothing)
// copy remaining elements as it is
for (int j = i + 2; j < arr.size(); j++) {
temp.push_back(arr[j]);
}
changed = true;
break;
}
else {
temp.push_back(arr[i]);
}
}
// if no pair found, array remains same
if (changed)
arr = temp;
}
return arr;
}
int main() {
vector<int> arr = {10, -5, -8, 2, -5};
vector<int> result = reducePairs(arr);
for (int i = 0; i < result.size(); i++) {
cout << result[i] << " ";
}
return 0;
}
import java.util.ArrayList;
import java.util.List;
class GfG {
static ArrayList<Integer> reducePairs(int[] arr) {
boolean changed = true;
// convert array to list for easier manipulation
ArrayList<Integer> list = new ArrayList<>();
for (int x : arr) list.add(x);
while (changed) {
changed = false;
ArrayList<Integer> temp = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
// check next element exists and signs are opposite
if (i + 1 < list.size()
&& list.get(i) * list.get(i + 1) < 0) {
int a = list.get(i), b = list.get(i + 1);
if (Math.abs(a) > Math.abs(b)) {
temp.add(a);
}
else if (Math.abs(a) < Math.abs(b)) {
temp.add(b);
}
// if equal, both removed (do nothing)
// copy remaining elements as it is
for (int j = i + 2; j < list.size(); j++) {
temp.add(list.get(j));
}
changed = true;
break;
}
else {
temp.add(list.get(i));
}
}
// if no pair found, array remains same
if (changed)
list = temp;
}
return list;
}
public static void main(String[] args) {
int[] arr = {10, -5, -8, 2, -5};
ArrayList<Integer> result = reducePairs(arr);
for (int x : result) {
System.out.print(x + " ");
}
}
}
def reducePairs(arr):
changed = True
while changed:
changed = False
temp = []
for i in range(len(arr)):
# check next element exists and signs are opposite
if i + 1 < len(arr) and arr[i] * arr[i + 1] < 0:
a = arr[i]
b = arr[i + 1]
if abs(a) > abs(b):
temp.append(a)
elif abs(a) < abs(b):
temp.append(b)
# if equal, both removed (do nothing)
# append remaining elements
temp.extend(arr[i + 2:])
changed = True
break
else:
temp.append(arr[i])
# if no pair found, array remains same
if changed:
arr = temp
return arr
if __name__ == '__main__':
arr = [10, -5, -8, 2, -5]
result = reducePairs(arr)
for i in range(len(result)):
print(result[i], end=' ')
using System;
using System.Collections.Generic;
class GfG
{
static List<int> reducePairs(int[] arr)
{
bool changed = true;
// convert array to list for easier updates
List<int> list = new List<int>(arr);
while (changed)
{
changed = false;
List<int> temp = new List<int>();
for (int i = 0; i < list.Count; i++)
{
if (i + 1 < list.Count && list[i] * list[i + 1] < 0)
{
int a = list[i], b = list[i + 1];
if (Math.Abs(a) > Math.Abs(b))
temp.Add(a);
else if (Math.Abs(a) < Math.Abs(b))
temp.Add(b);
// if equal, both removed (do nothing)
// copy remaining elements directly
for (int j = i + 2; j < list.Count; j++)
temp.Add(list[j]);
changed = true;
break;
}
else
{
temp.Add(list[i]);
}
}
// if no pair found, array remains same
if (changed)
list = temp;
}
return list;
}
public static void Main()
{
int[] arr = { 10, -5, -8, 2, -5 };
List<int> result = reducePairs(arr);
foreach (int x in result)
{
Console.Write(x + " ");
}
}
}
function reducePairs(arr) {
let changed = true;
while (changed) {
changed = false;
let temp = [];
for (let i = 0; i < arr.length; i++) {
// check next element exists and signs are opposite
if (i + 1 < arr.length && arr[i] * arr[i + 1] < 0) {
let a = arr[i], b = arr[i + 1];
if (Math.abs(a) > Math.abs(b)) {
temp.push(a);
}
else if (Math.abs(a) < Math.abs(b)) {
temp.push(b);
}
// if equal → both removed (do nothing)
// copy remaining elements
for (let j = i + 2; j < arr.length; j++) {
temp.push(arr[j]);
}
changed = true;
break;
} else {
temp.push(arr[i]);
}
}
// if no pair found, array remains same
if (changed) arr = temp;
}
return arr;
}
// Driver code
let arr = [10, -5, -8, 2, -5];
let result = reducePairs(arr);
for (let i = 0; i < result.length; i++) {
console.log(result[i] + " ");
}
[Expected Approach] Using Stack - O(n) Time and O(n) Space
The idea is to traverse the array and use a stack to store elements. For each element, resolve collisions with the stack top whenever they have opposite signs, by removing the smaller absolute value or both if equal. Continue this process until no conflict remains, then push the current element. The stack finally contains the valid elements after handling all adjacent opposite sign interactions.
#include <iostream>
#include <vector>
using namespace std;
vector<int> reducePairs(vector<int>& arr) {
vector<int> s;
// Traverse each element
for (int element : arr) {
// Process while there is a collision (opposite signs)
while (!s.empty() && s.back() * element < 0) {
int top = s.back();
// Top has larger absolute value, keep top
if (abs(top) > abs(element)) {
element = top;
s.pop_back();
}
// Current element has larger absolute value
// keep current element
else if (abs(top) < abs(element)) {
s.pop_back();
}
// Both have same absolute value, both removed
else {
s.pop_back();
element = 0;
break;
}
}
// If current element still exists, push into stack
if (element != 0)
s.push_back(element);
}
return s;
}
int main() {
vector<int> arr = {10, -5, -8, 2, -5};
vector<int> result = reducePairs(arr);
for (int i = 0; i < result.size(); i++) {
cout << result[i] << " ";
}
return 0;
}
import java.util.ArrayList;
class GfG {
static ArrayList<Integer> reducePairs(int[] arr) {
ArrayList<Integer> s = new ArrayList<>();
// Traverse each element
for (int element : arr) {
// Process while there is a collision (opposite signs)
while (!s.isEmpty() && s.get(s.size() - 1) * element < 0) {
int top = s.get(s.size() - 1);
// Top has larger absolute value, keep top
if (Math.abs(top) > Math.abs(element)) {
element = top;
s.remove(s.size() - 1);
}
// Current element has larger absolute value
// keep current element
else if (Math.abs(top) < Math.abs(element)) {
s.remove(s.size() - 1);
}
// Both have same absolute value, both removed
else {
s.remove(s.size() - 1);
element = 0;
break;
}
}
// If current element still exists, push into stack
if (element != 0)
s.add(element);
}
return s;
}
public static void main(String[] args) {
int[] arr = {10, -5, -8, 2, -5};
ArrayList<Integer> result = reducePairs(arr);
for (int i = 0; i < result.size(); i++) {
System.out.print(result.get(i) + " ");
}
}
}
def reducePairs(arr):
s = []
# Traverse each element
for element in arr:
# Process while there is a collision (opposite signs)
while s and s[-1] * element < 0:
top = s[-1]
# Top has larger absolute value, keep top
if abs(top) > abs(element):
element = top
s.pop()
# Current element has larger absolute value
# keep current element
elif abs(top) < abs(element):
s.pop()
# Both have same absolute value, both removed
else:
s.pop()
element = 0
break
# If current element still exists, push into stack
if element!= 0:
s.append(element)
return s
if __name__ == '__main__':
arr = [10, -5, -8, 2, -5]
result = reducePairs(arr)
for i in result:
print(i, end=' ')
using System;
using System.Collections.Generic;
class GfG {
static List<int> reducePairs(int[] arr)
{
List<int> s = new List<int>();
// Traverse each element
foreach(int elementVal in arr)
{
int element = elementVal;
// Process while there is a collision (opposite
// signs)
while (s.Count > 0
&& s[s.Count - 1] * element < 0) {
int top = s[s.Count - 1];
// Top has larger absolute value, keep top
if (Math.Abs(top) > Math.Abs(element)) {
element = top;
s.RemoveAt(s.Count - 1);
}
// Current element has larger absolute value
// keep current element
else if (Math.Abs(top)
< Math.Abs(element)) {
s.RemoveAt(s.Count - 1);
}
// Both have same absolute value, both
// removed
else {
s.RemoveAt(s.Count - 1);
element = 0;
break;
}
}
// If current element still exists, push into
// stack
if (element != 0)
s.Add(element);
}
return s;
}
public static void Main()
{
int[] arr = { 10, -5, -8, 2, -5 };
List<int> result = reducePairs(arr);
foreach(int i in result) { Console.Write(i + " "); }
}
}
function reducePairs(arr) {
let s = [];
// Traverse each element
for (let element of arr) {
// Process while there is a collision (opposite signs)
while (s.length > 0 && s[s.length - 1] * element < 0) {
let top = s[s.length - 1];
// Top has larger absolute value, keep top
if (Math.abs(top) > Math.abs(element)) {
element = top;
s.pop();
}
// Current element has larger absolute value
// keep current element
else if (Math.abs(top) < Math.abs(element)) {
s.pop();
}
// Both have same absolute value, both removed
else {
s.pop();
element = 0;
break;
}
}
// If current element still exists, push into stack
if (element!= 0)
s.push(element);
}
return s;
}
// Driver code
let arr = [10, -5, -8, 2, -5];
let result = reducePairs(arr);
for (let i = 0; i < result.length; i++) {
console.log(result[i] + " ");
}
Output
10