You are given n cubes as an array cubes[] in a certain order and contains only distinct elements. Your task is to build towers using them. Whenever two cubes are one on top of the other, the upper cube must be smaller than the lower cube. You must process the cubes in the given order. You can always either place the cube on top of an existing tower or begin a new tower. What is the minimum possible number of towers?
Examples:
Input: n = 5, cubes[] = {3, 8, 2, 1, 5}
Output: 2
Explanation: We can make 2 towers {3, 2, 1} and {8, 5}.
Input: n = 4, cubes[] = {4, 3, 1, 2}
Output: 2
Explanation: We can make 2 towers {4, 3, 1} and {2}.
Input: n = 4, cubes[] = {2,2,1,1}
Output: 2
Explanation: We can make 2 towers {2,1} and {2,1}.
Approach: To solve the problem, follow the below idea:
We can solve the problem by iterating over the cubes and for every cube, we will find the smallest cube which is larger than the current cube and is placed on the top of any tower. This can be done by storing only the top elements of the tower in a multiset. So, for every block we find the tower that has the topmost block just greater than the current block. This can be easily found using Binary Search upper bound on multiset. Also, whenever we add a block to a tower, we need to update the top of the tower as well.
Step-by-step algorithm:
- Maintain a variable, say ans to store the number of towers needed.
- Maintain a multiset, say topElements store the topmost cubes of all towers.
- For each cube with size cubes[i], find the smallest cube which has size > cubes[i] and is among the top-most cubes of towers.
- If there is no cube among the top-most cubes which has size > cubes[i], then we have to make another tower.
- Otherwise, if there is a cube among the top-most cubes which has size > cubes[i], then we place the current cube on top of it.
- After all the iterations, return ans as the final answer.
Below is the implementation of the algorithm:
C++
#include <bits/stdc++.h>
#define ll long long
using namespace std;
// function to find the minimum number of towers
ll solve(ll N, vector<ll>& cubes)
{
// Variable to store the number of twers
ll ans = 0;
// Multiset to store the size of top most cubes of all
// towers
multiset<ll> topElements;
for (int i = 0; i < N; i++) {
// Find the smallest cube which is larger than
// cubes[i]
auto it = topElements.upper_bound(cubes[i]);
// If no cube has size > cubes[i], then we need
// another tower for this block
if (it == topElements.end()) {
ans++;
topElements.insert(cubes[i]);
}
// If there is a cube which has size > cubes[i],
// place cubes[i] on top of it.
else {
topElements.erase(it);
topElements.insert(cubes[i]);
}
}
return ans;
}
int main()
{
// Sample Input
ll N = 5;
vector<ll> cubes = { 3, 8, 2, 1, 5 };
cout << solve(N, cubes);
}
Java
import java.util.*;
import java.util.Map.*;
public class Main {
// function to find the minimum number of towers
static long solve(long N, ArrayList<Long> cubes) {
// Variable to store the number of towers
long ans = 0;
// Multiset to store the size of top most cubes of all towers and their count
TreeMap<Long, Integer> topElements = new TreeMap<>();
for (int i = 0; i < N; i++) {
// Find the smallest cube which is larger than cubes[i]
Entry<Long, Integer> entry = topElements.higherEntry(cubes.get(i));
// If no cube has size > cubes[i], then we need another tower for this block
if (entry == null) {
ans++;
}
// If there is a cube which has size > cubes[i], place cubes[i] on top of it.
else {
if(entry.getValue() == 1) {
// remove that element
topElements.remove(entry.getKey());
} else {
topElements.put(entry.getKey(), entry.getValue() - 1);
}
}
topElements.put(cubes.get(i), topElements.getOrDefault(cubes.get(i), 0)+1);
}
return ans;
}
public static void main(String[] args) {
// Sample Input
long N = 5;
ArrayList<Long> cubes = new ArrayList<>(Arrays.asList(3L, 8L, 2L, 1L, 5L));
System.out.println(solve(N, cubes));
}
}
Python
from bisect import bisect_right
# Function to find the minimum number of towers
def solve(N, cubes):
# Variable to store the number of towers
ans = 0
# List to store the size of top most cubes of all towers
top_elements = []
for i in range(N):
# Find the index of the smallest cube which is larger than cubes[i]
index = bisect_right(top_elements, cubes[i])
# If no cube has size > cubes[i], then we need another tower for this block
if index == len(top_elements):
ans += 1
top_elements.append(cubes[i])
# If there is a cube which has size > cubes[i], place cubes[i] on top of it.
else:
top_elements[index] = cubes[i]
top_elements.sort() # Sorting after replacing the cube ensures top_elements remains sorted
return ans
def main():
# Sample Input
N = 5
cubes = [3, 8, 2, 1, 5]
print(solve(N, cubes))
if __name__ == "__main__":
main()
C#
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
public static long Solve(long N, List<long> cubes)
{
long ans = 0;
// List to simulate the behavior of a multiset for top elements of towers
List<long> topElements = new List<long>();
foreach (var cube in cubes)
{
// Find the index of the smallest cube which is larger than `cube`
var index = topElements.FindIndex(x => x > cube);
if (index == -1)
{
ans++;
topElements.Add(cube); // If no such cube, add a new tower
}
else
{
topElements[index] = cube; // Replace the top cube of the found tower
}
topElements.Sort(); // Keep topElements sorted
}
return ans;
}
static void Main(string[] args)
{
long N = 5;
List<long> cubes = new List<long> { 3, 8, 2, 1, 5 };
Console.WriteLine(Solve(N, cubes));
}
}
JavaScript
function GFG(N, cubes) {
// Variable to store the number of the towers
let ans = 0;
let topElements = new Set();
for (let i = 0; i < N; i++) {
// Find the smallest cube which is larger than cubes[i]
let it = Array.from(topElements).findIndex(c => c > cubes[i]);
if (it === -1) {
ans++;
topElements.add(cubes[i]);
}
// If there is a cube which has size > cubes[i]
// place cubes[i] on top of it
else {
topElements.delete(cubes[it]);
topElements.add(cubes[i]);
}
}
return ans;
}
// Sample Input
let N = 5;
let cubes = [3, 8, 2, 1, 5];
console.log(GFG(N, cubes));
Time Complexity: O(N * logN), where N is the number of cubes.
Auxiliary Space: O(N)
Similar Reads
CSES Solutions - Tower of Hanoi The Tower of Hanoi game consists of three stacks (left, middle, and right) and n round disks of different sizes. Initially, the left stack has all the disks, in increasing order of size from top to bottom. The goal is to move all the disks to the right stack using the middle stack. On each move, you
6 min read
CSES Problem Set Solutions In this article, we have compiled comprehensive, high-quality tutorials on the CSES Problem Set Solutions to assist you in understanding the problem set for learning algorithmic programming. What is CSES Problem Set?CSES Problem Set is a collection of competitive programming tasks hosted on the CSES
8 min read
Implement Tower of Hanoi in C++ Tower of Hanoi is mathematical puzzle in which we have 3 rods and n disks. First, all the disks are arranged in first rod from larger disk to smaller disk. We have to move all the disk from the first disk to last disk in same arrangement from larger to smaller. Rules of Tower of HanoiThere are follo
3 min read
Minimize cost of operation to equalize tower heights Given the heights of n towers in the array heights[], the task is to make all towers the same height by either adding or removing blocks.Each addition or removal operation has a different cost for each tower, specified in the array cost[].The objective is to minimize the total cost required to equal
15+ min read
Iterative Tower of Hanoi The Tower of Hanoi is a mathematical puzzle with three poles and stacked disks of different sizes. The goal is to move all disks from the source pole to the destination pole using an auxiliary pole, following two rules:Only one disk can be moved at a time.A larger disk cannot be placed on a smaller
6 min read