CSES Solutions - Collecting Numbers II
Last Updated :
15 Apr, 2024
Given an array that contains each number between 1 to n exactly once. Your task is to collect the numbers from 1 to n in increasing order. On each round, you go through the array from left to right and collect as many numbers as possible. Given m operations that swap two numbers in the array, your task is to report the number of rounds after each operation.
Examples:
Input: n = 5, m = 3, values[] = {4, 2, 1, 5, 3}, swaps[][] = {{2, 3}, {1, 5}, {2,3}}
Output:
2
3
4
Explanation:
- In the 1st operation after swapping the values of 2nd and 3rd position the array is {4, 1, 2, 5, 3}. We can collect 1, 2, 3 in the 1st round and 4, 5 in the 2nd round. Hence, the answer is 2.
- In the 2nd operation after swapping the values of 1st and 5th position the array is {3, 1, 2, 5, 4}. We can collect 1, 2 in the 1st round, 3, 4 in the 2nd round and 5 in the 3rd round. Hence, the answer is 3.
- In the 3rd operation after swapping the values of 2nd and 3rd position the array is {3, 2, 1, 5, 4}. We can collect 1 in the 1st round, 2 in the 2nd round, 3, 4 in the 3rd round and 5 in the 4th round. Hence, the answer is 4.
Input: n = 4, m = 1, values[] = {4, 2, 3, 1}, swaps[][] = {{1, 4}}
Output: 1
Explanation: After the first swap operation, the array will be {1, 2, 3, 4}. We can collect 1, 2, 3 and 4 in the first round only.
Approach: To solve the problem, follow the idea below:
The idea is to calculate the number of inversions, where values[i] > values[j] and position[i] < position[j], between adjacent elements. This will give us the number of rounds required to collect all numbers from 1 to n in the given order. Count the number of inversions formed by given order of elements. Begin the operation. Since only the adjacent elements (the previous and next element of the current element) are affected, we store them in a set if they exist. Then subtract from the count, the inversions formed by our current set as there may be some elements that don’t form an inversion after the swap and if they form they'll be counted. Next, we swap the elements, update the positions, and again count and add the inversions by adjacent elements to our existing count. This approach reduces the time complexity by checking only the neighboring elements.
Step-by-step algorithm:
- Create a vector to store the positions of each value in the array.
- Initialize a count variable to 1.
- Iterate over the array from 1 to n-1.
- If there is an inversion i.e. the position of the current value is greater than the position of the next value, increment the count.
- Declare a set to store the pairs of values that will be updated in each swap operation.
- Update the count before the swap, subtract from the count, the inversions formed by our current set as there may be some elements that don’t form an inversion after the swap and if they form they'll be counted.
- Swap the values at the given positions.
- Update the positions of the swapped values.
- Count and add the inversions by adjacent elements to our existing count.
- Add the count to the result vector.
- Clear the set for the next operation.
- Return the result.
Below is the implementation of the algorithm:
C++
// C++ code
#include <bits/stdc++.h>
using namespace std;
vector<int>
collectingnumbersII(int n, int m, vector<int>& values,
vector<vector<int> >& swaps)
{
// Make the array 1-indexed
values.insert(values.begin(), 0);
vector<int> res;
vector<int> position(n + 1);
// Store the positions of the values
for (int i = 1; i <= n; i++)
position[values[i]] = i;
// Calculate the initial number of rounds
int count = 1;
for (int i = 1; i < n; i++)
// Increase the count if there is an inversion i.e.
// if the position of i is greater than the position
// of i+1
count += (position[i] > position[i + 1]);
// Declare a set to store the pairs of values that will
// be updated
set<pair<int, int> > updatedPairs;
for (int i = 0; i < m; i++) {
// Declare two integers l and r to store the
// positions to be swapped
int l = swaps[i][0], r = swaps[i][1];
// Insert the pairs of values that will be updated
// into the set
if (values[l] + 1 <= n)
updatedPairs.insert(
{ values[l], values[l] + 1 });
if (values[l] - 1 >= 1)
updatedPairs.insert(
{ values[l] - 1, values[l] });
if (values[r] + 1 <= n)
updatedPairs.insert(
{ values[r], values[r] + 1 });
if (values[r] - 1 >= 1)
updatedPairs.insert(
{ values[r] - 1, values[r] });
// Update the count before the swap
for (auto swapped : updatedPairs)
// Subtract from the count, the inversions
// formed by our current set as there may be
// some elements that don’t form an inversion
// after the swap and if they form they'll be
// counted.
count -= position[swapped.first]
> position[swapped.second];
// Perform the swap
swap(values[l], values[r]);
// Update the position of the value at position l
position[values[l]] = l;
// Update the position of the value at position r
position[values[r]] = r;
// Update the count after the swap
for (auto swapped : updatedPairs)
// Count and add the inversions by adjacent
// elements to our existing count.
count += position[swapped.first]
> position[swapped.second];
// Add the count to the result vector.
res.push_back(count);
// Clear the set for the next operation
updatedPairs.clear();
}
// Return result
return res;
}
// Driver Code
int main()
{
int n = 5, m = 3;
vector<int> values = { 4, 2, 1, 5, 3 };
vector<vector<int> > swaps
= { { 2, 3 }, { 1, 5 }, { 2, 3 } };
vector<int> res
= collectingnumbersII(n, m, values, swaps);
for (auto i : res)
cout << i << "\n";
return 0;
}
Java
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Main {
public static List<Integer> GFG(int n, int m, int[] values, int[][] swaps) {
// Make the array 1-indexed
List<Integer> res = new ArrayList<>();
int[] position = new int[n + 1];
// Store the positions of the values
for (int i = 1; i <= n; i++) {
position[values[i]] = i;
}
// Calculate the initial number of rounds
int count = 1;
for (int i = 1; i < n; i++) {
// Increase the count if there is an inversion i.e.
// if the position of i is greater than the position
// of i+1
count += position[i] > position[i + 1] ? 1 : 0;
}
// Declare a set to store the pairs of the values that will
// be updated
Set<List<Integer>> updatedPairs = new HashSet<>();
for (int i = 0; i < m; i++) {
int l = swaps[i][0];
int r = swaps[i][1];
// Insert the pairs of the values that will be updated
// into the set
if (values[l] + 1 <= n) {
updatedPairs.add(List.of(values[l], values[l] + 1));
}
if (values[l] - 1 >= 1) {
updatedPairs.add(List.of(values[l] - 1, values[l]));
}
if (values[r] + 1 <= n) {
updatedPairs.add(List.of(values[r], values[r] + 1));
}
if (values[r] - 1 >= 1) {
updatedPairs.add(List.of(values[r] - 1, values[r]));
}
// Update the count before the swap
for (List<Integer> swapped : updatedPairs) {
count -= position[swapped.get(0)] > position[swapped.get(1)] ? 1 : 0;
}
// Perform the swap
int temp = values[l];
values[l] = values[r];
values[r] = temp;
// Update the position of value at position l
position[values[l]] = l;
position[values[r]] = r;
// Update the count after the swap
for (List<Integer> swapped : updatedPairs) {
count += position[swapped.get(0)] > position[swapped.get(1)] ? 1 : 0;
}
// Add the count to result list
res.add(count);
updatedPairs.clear();
}
// Return result
return res;
}
// Driver Code
public static void main(String[] args) {
int n = 5, m = 3;
int[] values = {0, 4, 2, 1, 5, 3}; // Make the array 1-indexed
int[][] swaps = {{2, 3}, {1, 5}, {2, 3}};
List<Integer> res = GFG(n, m, values, swaps);
for (int i : res) {
System.out.println(i);
}
}
}
Python
def GFG(n, m, values, swaps):
# Make the array 1-indexed
values.insert(0, 0)
res = []
position = [0] * (n + 1)
# Store the positions of the values
for i in range(1, n + 1):
position[values[i]] = i
# Calculate the initial number of rounds
count = 1
for i in range(1, n):
# Increase the count if there is an inversion i.e.
# if the position of i is greater than the position
# of i+1
count += position[i] > position[i + 1]
# Declare a set to the store the pairs of the values that will
# be updated
updated_pairs = set()
for i in range(m):
l, r = swaps[i]
# Insert the pairs of the values that will be updated
# into the set
if values[l] + 1 <= n:
updated_pairs.add((values[l], values[l] + 1))
if values[l] - 1 >= 1:
updated_pairs.add((values[l] - 1, values[l]))
if values[r] + 1 <= n:
updated_pairs.add((values[r], values[r] + 1))
if values[r] - 1 >= 1:
updated_pairs.add((values[r] - 1, values[r]))
# Update the count before the swap
for swapped in updated_pairs:
count -= position[swapped[0]] > position[swapped[1]]
# Perform the swap
values[l], values[r] = values[r], values[l]
# Update the position of value at position l
position[values[l]] = l
position[values[r]] = r
# Update the count after the swap
for swapped in updated_pairs:
count += position[swapped[0]] > position[swapped[1]]
# Add the count to result list.
res.append(count)
updated_pairs.clear()
# Return result
return res
# Driver Code
if __name__ == "__main__":
n, m = 5, 3
values = [4, 2, 1, 5, 3]
swaps = [[2, 3], [1, 5], [2, 3]]
res = GFG(n, m, values, swaps)
for i in res:
print(i)
JavaScript
function GFG(n, m, values, swaps) {
// Make the array 1-indexed
values.unshift(0);
let res = [];
let position = new Array(n + 1).fill(0);
// Store the positions of the values
for (let i = 1; i <= n; i++) {
position[values[i]] = i;
}
// Calculate the initial number of rounds
let count = 1;
for (let i = 1; i < n; i++) {
// Increase the count if there is an inversion i.e.
// if the position of i is greater than the position
// of i+1
count += position[i] > position[i + 1];
}
// Declare a set to store the pairs of the values that will
// be updated
let updatedPairs = new Set();
for (let i = 0; i < m; i++) {
let [l, r] = swaps[i];
// Insert the pairs of the values that will be updated
// into the set
if (values[l] + 1 <= n) {
updatedPairs.add([values[l], values[l] + 1]);
}
if (values[l] - 1 >= 1) {
updatedPairs.add([values[l] - 1, values[l]]);
}
if (values[r] + 1 <= n) {
updatedPairs.add([values[r], values[r] + 1]);
}
if (values[r] - 1 >= 1) {
updatedPairs.add([values[r] - 1, values[r]]);
}
// Update the count before the swap
for (let swapped of updatedPairs) {
count -= position[swapped[0]] > position[swapped[1]];
}
// Perform the swap
[values[l], values[r]] = [values[r], values[l]];
// Update the position of value at position l
position[values[l]] = l;
position[values[r]] = r;
// Update the count after the swap
for (let swapped of updatedPairs) {
count += position[swapped[0]] > position[swapped[1]];
}
// Add the count to result list
res.push(count);
updatedPairs.clear();
}
// Return result
return res;
}
// Driver Code
let n = 5, m = 3;
let values = [4, 2, 1, 5, 3];
let swaps = [[2, 3], [1, 5], [2, 3]];
let res = GFG(n, m, values, swaps);
for (let i of res) {
console.log(i);
}
Time Complexity: O(n), where n is the size of the array.
Auxiliary Space: O(n), where n is the size of the array.
Similar Reads
Non-linear Components In electrical circuits, Non-linear Components are electronic devices that need an external power source to operate actively. Non-Linear Components are those that are changed with respect to the voltage and current. Elements that do not follow ohm's law are called Non-linear Components. Non-linear Co
11 min read
Spring Boot Tutorial Spring Boot is a Java framework that makes it easier to create and run Java applications. It simplifies the configuration and setup process, allowing developers to focus more on writing code for their applications. This Spring Boot Tutorial is a comprehensive guide that covers both basic and advance
10 min read
Dynamic Programming or DP Dynamic Programming is an algorithmic technique with the following properties.It is mainly an optimization over plain recursion. Wherever we see a recursive solution that has repeated calls for the same inputs, we can optimize it using Dynamic Programming. The idea is to simply store the results of
3 min read
Class Diagram | Unified Modeling Language (UML) A UML class diagram is a visual tool that represents the structure of a system by showing its classes, attributes, methods, and the relationships between them. It helps everyone involved in a projectâlike developers and designersâunderstand how the system is organized and how its components interact
12 min read
Python Variables In Python, variables are used to store data that can be referenced and manipulated during program execution. A variable is essentially a name that is assigned to a value. Unlike many other programming languages, Python variables do not require explicit declaration of type. The type of the variable i
6 min read
Spring Boot Interview Questions and Answers Spring Boot is a Java-based framework used to develop stand-alone, production-ready applications with minimal configuration. Introduced by Pivotal in 2014, it simplifies the development of Spring applications by offering embedded servers, auto-configuration, and fast startup. Many top companies, inc
15+ min read
Backpropagation in Neural Network Back Propagation is also known as "Backward Propagation of Errors" is a method used to train neural network . Its goal is to reduce the difference between the modelâs predicted output and the actual output by adjusting the weights and biases in the network.It works iteratively to adjust weights and
9 min read
Polymorphism in Java Polymorphism in Java is one of the core concepts in object-oriented programming (OOP) that allows objects to behave differently based on their specific class type. The word polymorphism means having many forms, and it comes from the Greek words poly (many) and morph (forms), this means one entity ca
7 min read
CTE in SQL In SQL, a Common Table Expression (CTE) is an essential tool for simplifying complex queries and making them more readable. By defining temporary result sets that can be referenced multiple times, a CTE in SQL allows developers to break down complicated logic into manageable parts. CTEs help with hi
6 min read
What is an Operating System? An Operating System is a System software that manages all the resources of the computing device. Acts as an interface between the software and different parts of the computer or the computer hardware. Manages the overall resources and operations of the computer. Controls and monitors the execution o
5 min read