Recently while practicing I came across this problem , here is an excerpt from it,
A permutation of the numbers 1, ..., N is a rearrangment of these numbers. For example
2 4 5 1 7 6 3 8
is a permutation of 1,2, ..., 8. Of course,
1 2 3 4 5 6 7 8
is also a permutation of 1, 2, ..., 8.
Associated with each permutation of N is a special sequence of positive integers of length N called its inversion sequence. The ith element of this sequence is the number of numbers j that are strictly less than i and appear to the right of i in this permutation. For the permutation
2 4 5 1 7 6 3 8
the inversion sequence is
0 1 0 2 2 1 2 0
The 2nd element is 1 because 1 is strictly less than 2 and it appears to the right of 2 in this permutation. Similarly, the 5th element is 2 since 1 and 3 are strictly less than 5 but appear to the right of 5 in this permutation and so on.
As another example, the inversion sequence of the permutation
8 7 6 5 4 3 2 1
is
0 1 2 3 4 5 6 7
In this problem, you will be given the inversion sequence of some permutation. Your task is to reconstruct the permutation from this sequence.
I cooked up two solutions but both fail to deliver the result in time for the last three testcases,
here is the code,
Solution 1
#include <iostream>
#include <vector>
int main(){
int n;
std::cin >> n;
std::vector<int>nums(n);
int key;
for( int k = 0; k < n; k++ ){
std::cin >> key;
int value = k+1;
int i = 0;
for(i = 0; i < key; i++){
int j = k - i;
nums[j] = nums[j - 1];
}
nums[k - i] = value;
}
for(int i = 0;i < n;i ++){
std::cout << nums[i] << " ";
}
std::cout << std::endl;
return 0;
}
Simple and easy to understand , get the key and shift the integers to right to accommodate the new integer.
Solution 2
#include <iostream>
#include <vector>
int main(){
int n;
std::cin >> n;
std::vector<int>nums(n,0);
std::vector<int>inverse(n);
for(int k = 0; k < n; k++ ){
std::cin >> inverse[k];
}
for(int i=n-1;i>=0;i--){
int onRight = inverse[i];
int pos = i;
for(int j=n-1;j>=0;j--){
if(nums[j] == 0){
pos = j;
break;
}
}
while(onRight){
if(nums[pos] == 0){
onRight--;
}
pos--;
}
if(nums[pos] != 0){
for(int j=pos;j>=0;j--){
if(nums[j] == 0){
pos = j;
break;
}
}
}
nums[pos] = i+1;
}
for(int i = 0;i < n;i ++){
std::cout << nums[i] << " ";
}
std::cout << std::endl;
return 0;
}
This one is a little bit complicated in code but it follows a simple concept that push the integer from back , if the block is empty then decrement the number small of integers right of it , if not skip it to the next block and fill the array.
Both the solutions take almost same time , is there any better approach for it available?
Here are the testcases.