Open In App

Reduce Array by replacing pair with their difference

Last Updated : 20 Dec, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

You are given an array of positive integers. You can perform the following operations on the array any number of times:

  • Select the two largest elements in the array, suppose a and b.
  • If a = b, remove both of them from the array.
  • If a > b, remove b and the new value of a will be a-b or vice-versa.

This process continues until there is either one element left or all the elements have been removed. You have to find the last element remaining or return 0 if there is none.

Examples:

Input: [1, 2, 3, 6, 7, 7]
Output: 0
Explanation: We start with two largest elements. In this case, they are two equal elements with value 7, so they both are removed. Then, the next elements are 3 and 6. Discard the smaller one and the larger one will now be of length 6-3 = 3. Then, the next elements are of 3 and 2. Again the smaller will be discarded and larger one will now be 3-2 = 1. Now there are two equal elements, 1, hence both will be discarded and output will be 0.

Input: [2, 4, 5]
Output: 1
Explanation: In this case, the two largest elements are 4 and 5. As 4 is smaller it will be discarded and the larger will become 5-4 = 1. Now there are only two elements remaining which are 1 and 2. Hence 1 will be discarded and the final output will be 2-1 = 1.

Approach:

As the problem has to repeatedly find the two largest items from a given array, we can think of a priority queue (Max heap) in this case. Using a max heap, we can perform the required operations until the given condition is reached.

Follow the below steps to implement the above idea:

  • Create a priority queue (max heap) named ‘pq’ to store the items in a decreasingly sorted manner.
  • Traverse through the array and insert each item into the heap.
  • Till there are atleast 2 items in the heap, perform the following operations as stated in the problem:
    • Store the two largest elements from the max-heap in two different variables named as ‘a’ and ‘b’.
    • If the values of ‘a’ and ‘b’ are not equal, reduce the length of ‘b’ from ‘a’.
    • Push the updated value of ‘a’ into the max-heap and continue performing these steps.
  • Once these above operations are performed, check if the size of pq is 1.
  • If it is equal to 1, that means one element is remaining which cannot be integrated further. So return the element as our answer.
  • If it is not 1, then all the elements have been removed and none is remaining. So we return 0 as our answer.

Implementation of the above approach:

C++




// C++ code for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the last element remaining
int lastElement(vector<int>& arr)
{
    int n = arr.size();
    // Create a max heap
    priority_queue<int> pq;
 
    // Push all the elements into the heap
    for (int i = 0; i < n; i++) {
        pq.push(arr[i]);
    }
 
    // Perform the operations till the size of heap is
    // greater than 1
    while (pq.size() > 1) {
        // Pop the top two elements
        int a = pq.top();
        pq.pop();
        int b = pq.top();
        pq.pop();
 
        // If both the elements are not equal
        if (a != b) {
            // Reduce the length of the larger element
            a -= b;
            // Push the updated value into the heap
            pq.push(a);
        }
    }
 
    // If one element is left return its value
    if (pq.size() == 1) {
        return pq.top();
    }
 
    // If no element is left return 0
    return 0;
}
 
// Driver Code
int main()
{
    // Input vector
    vector<int> arr = { 2, 4, 5 };
    // Function call
    cout << lastElement(arr) << endl;
    return 0;
}


Java




// Java Code for the above approach
 
import java.util.*;
 
public class GFG {
    // Function to find the last element remaining
    public static int lastElement(int[] arr)
    {
        int n = arr.length;
        // Create a max heap
        PriorityQueue<Integer> pq = new PriorityQueue<>(
            (a, b) -> Integer.compare(b, a));
 
        // Push all the elements into the heap
        for (int i = 0; i < n; i++) {
            pq.add(arr[i]);
        }
 
        // Perform the operations until the size of the heap
        // is greater than 1
        while (pq.size() > 1) {
            // Pop the top two elements
            int a = pq.poll();
            int b = pq.poll();
 
            // If both the elements are not equal
            if (a != b) {
                // Reduce the length of the larger element
                a -= b;
                // Push the updated value into the heap
                pq.add(a);
            }
        }
 
        // If one element is left, return its value
        if (pq.size() == 1) {
            return pq.peek();
        }
 
        // If no element is left, return 0
        return 0;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        // Input array
        int[] arr = { 1, 2, 3, 6, 7, 7 };
        // Function call
        System.out.println(lastElement(arr));
    }
}


Python3




import heapq
 
# Function to find the last element remaining
def last_element(arr):
    n = len(arr)
    # Create a max heap
    pq = [-x for x in arr]
    heapq.heapify(pq)
 
    # Perform the operations till the size of heap is
    # greater than 1
    while len(pq) > 1:
        # Pop the top two elements
        a = -heapq.heappop(pq)
        b = -heapq.heappop(pq)
 
        # If both the elements are not equal
        if a != b:
            # Reduce the length of the larger element
            a -= b
            # Push the updated value into the heap
            heapq.heappush(pq, -a)
 
    # If one element is left return its value
    if len(pq) == 1:
        return -pq[0]
 
    # If no element is left return 0
    return 0
 
# Driver Code
if __name__ == "__main__":
    # Input list
    arr = [2, 4, 5]
    # Function call
    print(last_element(arr))


C#




// C# program for the above approach
using System;
using System.Collections.Generic;
 
public class GFG {
    // Function to find the last element remaining
    static int LastElement(List<int> arr)
    {
        int n = arr.Count;
 
        // Create a max heap
        var pq = new PriorityQueue<int>();
 
        // Push all the elements into the heap
        for (int i = 0; i < n; i++) {
            pq.Push(arr[i]);
        }
 
        // Perform the operations till the size of heap is
        // greater than 1
        while (pq.Count > 1) {
            // Pop the top two elements
            int a = pq.Pop();
            int b = pq.Pop();
 
            // If both the elements are not equal
            if (a != b) {
                // Reduce the length of the larger element
                a -= b;
                // Push the updated value into the heap
                pq.Push(a);
            }
        }
 
        // If one element is left return its value
        if (pq.Count == 1) {
            return pq.Top();
        }
 
        // If no element is left return 0
        return 0;
    }
 
    // Driver Code
    static void Main()
    {
        // Input list
        List<int> arr = new List<int>{ 2, 4, 5 };
        // Function call
        Console.WriteLine(LastElement(arr));
    }
}
 
// Priority Queue Implementation
public class PriorityQueue<T> where T : IComparable<T> {
    private List<T> heap;
 
    public PriorityQueue() { heap = new List<T>(); }
 
    public int Count
    {
        get { return heap.Count; }
    }
 
    public void Push(T value)
    {
        heap.Add(value);
        int currentIndex = heap.Count - 1;
 
        while (currentIndex > 0) {
            int parentIndex = (currentIndex - 1) / 2;
            if (heap[currentIndex].CompareTo(
                    heap[parentIndex])
                > 0) {
                Swap(currentIndex, parentIndex);
                currentIndex = parentIndex;
            }
            else {
                break;
            }
        }
    }
 
    public T Pop()
    {
        if (Count == 0) {
            throw new InvalidOperationException(
                "Priority queue is empty");
        }
 
        T root = heap[0];
        heap[0] = heap[Count - 1];
        heap.RemoveAt(Count - 1);
 
        int currentIndex = 0;
        while (true) {
            int leftChildIndex = currentIndex * 2 + 1;
            int rightChildIndex = currentIndex * 2 + 2;
 
            if (leftChildIndex >= Count) {
                break;
            }
 
            int childIndex = leftChildIndex;
            if (rightChildIndex < Count
                && heap[rightChildIndex].CompareTo(
                       heap[leftChildIndex])
                       > 0) {
                childIndex = rightChildIndex;
            }
 
            if (heap[currentIndex].CompareTo(
                    heap[childIndex])
                < 0) {
                Swap(currentIndex, childIndex);
                currentIndex = childIndex;
            }
            else {
                break;
            }
        }
 
        return root;
    }
 
    public T Top()
    {
        if (Count == 0) {
            throw new InvalidOperationException(
                "Priority queue is empty");
        }
        return heap[0];
    }
 
    private void Swap(int index1, int index2)
    {
        T temp = heap[index1];
        heap[index1] = heap[index2];
        heap[index2] = temp;
    }
}
 
// This code is contributed by Susobhan Akhuli


Javascript




// Javascript program for the above approach
 
// Function to find the last element remaining
function lastElement(arr) {
    const n = arr.length;
    // Create a max heap
    const pq = new MaxHeap();
 
    // Push all the elements into the heap
    for (let i = 0; i < n; i++) {
        pq.push(arr[i]);
    }
 
    // Perform the operations until the size of heap is greater than 1
    while (pq.size() > 1) {
        // Pop the top two elements
        const a = pq.pop();
        const b = pq.pop();
 
        // If both the elements are not equal
        if (a !== b) {
            // Reduce the length of the larger element
            const diff = a - b;
            // Push the updated value into the heap
            pq.push(diff);
        }
    }
 
    // If one element is left return its value
    if (pq.size() === 1) {
        return pq.pop();
    }
 
    // If no element is left return 0
    return 0;
}
 
// MaxHeap class to simulate max heap functionality
class MaxHeap {
    constructor() {
        this.heap = [];
    }
 
    push(value) {
        this.heap.push(value);
        this.heapifyUp();
    }
 
    pop() {
        if (this.isEmpty()) {
            return null;
        }
        if (this.heap.length === 1) {
            return this.heap.pop();
        }
        const root = this.heap[0];
        this.heap[0] = this.heap.pop();
        this.heapifyDown();
        return root;
    }
 
    size() {
        return this.heap.length;
    }
 
    isEmpty() {
        return this.size() === 0;
    }
 
    heapifyUp() {
        let index = this.size() - 1;
        while (index > 0) {
            const parentIndex = Math.floor((index - 1) / 2);
            if (this.heap[index] > this.heap[parentIndex]) {
                this.swap(index, parentIndex);
                index = parentIndex;
            } else {
                break;
            }
        }
    }
 
    heapifyDown() {
        let index = 0;
        const length = this.size();
        while (true) {
            const leftChildIndex = 2 * index + 1;
            const rightChildIndex = 2 * index + 2;
            let largest = index;
            if (
                leftChildIndex < length &&
                this.heap[leftChildIndex] > this.heap[largest]
            ) {
                largest = leftChildIndex;
            }
            if (
                rightChildIndex < length &&
                this.heap[rightChildIndex] > this.heap[largest]
            ) {
                largest = rightChildIndex;
            }
            if (largest !== index) {
                this.swap(index, largest);
                index = largest;
            } else {
                break;
            }
        }
    }
 
    swap(i, j) {
        [this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]];
    }
}
 
// Driver Code
const arr = [2, 4, 5];
// Function call
console.log(lastElement(arr));
 
// This code is contributed by Susobhan Akhuli


Output

1









Time Complexity: O(N*log(N)). The all insertions in a priority queue takes O(N*log(N)) time and the time for each pop and top operation takes O(log(N)) time.
Auxiliary space: O(N),as we have used an extra space of a priority queue data structure.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads