Generate permutation of 1 to N with sum of min of prefix for each element as Y
Last Updated :
07 Apr, 2022
Given two integers N, Y, generate a permutation of length N such that sum of all prefix minimum of that permutation is Y.
Example:
Input: N = 5, Y = 10
Output: 5 2 1 4 3
Explanation: Array of prefix minimum for [5, 2, 1, 4, 3] is [5, 2, 1, 1, 1]. Sum of this array of prefix minimum is 10 (= Y).
Input: N = 5, Y = 5
Output: 1 2 3 4 5
Explanation: Array of prefix minimum for [1, 2, 3, 4, 5] is [1, 1, 1, 1, 1]. Sum of this array of prefix minimum is 5 (= Y).
Approach: The approach to solve this problem is based on below idea:
Suppose the remaining array to be created at some point of time be len and the remaining sum to be rem.
Greedily choose a value for this index by the given method below:
- let’s take Z value at this index, then we should have at least (Z + len – 1) = rem (By taking 1 at remaining indices).
- So, we get Z = (rem + 1 – len). Now, this value might be greater than len but we can’t take it. So, we will choose min(Z, len).
Follow the below steps to solve this problem:
- Now, a prefix minimum array for the required permutation is already built from the above greedy method.
- It might have duplicates as well. So, to remove that iterate over this array in reverse order and whenever arr[i] = arr[i-1], then put the smallest element not present at any index at ith index.
- In this way, ensured that the sum of prefix minimum should be Y and the array created should be permutation as well.
- Print the final array
Below is the implementation of the above approach:
C++
#include <iostream>
#include <set>
#include <vector>
using namespace std;
int findValue( long long N, long long Y)
{
return min(N, Y + 1 - N);
}
void generatePermutation( long long N, long long Y)
{
vector< int > ans(N);
if (Y < N || (2 * Y) > (N * (N + 1))) {
cout << -1 << endl;
return ;
}
set< int > s;
for ( int i = 1; i <= N; i++) {
s.insert(i);
}
for ( int i = 0; i < N; i++) {
int len = N - i;
int val = findValue(len, Y);
ans[i] = val;
Y -= val;
if (s.find(val) != s.end())
s.erase(val);
}
for ( int i = N - 1; i > 0; i--) {
if (ans[i] == ans[i - 1]) {
ans[i] = *s.begin();
s.erase(ans[i]);
}
}
for ( auto i : ans) {
cout << i << " " ;
}
cout << endl;
}
int main()
{
long long N = 5, Y = 10;
generatePermutation(N, Y);
return 0;
}
|
Java
import java.util.*;
class GFG {
static int findValue( int N, int Y)
{
return Math.min(N, Y + 1 - N);
}
static void generatePermutation( int N, int Y)
{
int [] ans = new int [N];
if (Y < N || ( 2 * Y) > (N * (N + 1 ))) {
System.out.println(- 1 );
return ;
}
Set<Integer> s = new HashSet<Integer>();
for ( int i = 1 ; i <= N; i++) {
s.add(i);
}
for ( int i = 0 ; i < N; i++) {
int len = N - i;
int val = findValue(len, Y);
ans[i] = val;
Y -= val;
if (s.contains(val))
s.remove(val);
}
for ( int i = N - 1 ; i > 0 ; i--) {
if (ans[i] == ans[i - 1 ]) {
ans[i] = s.stream().findFirst().get();
s.remove(ans[i]);
}
}
for ( int i = 0 ; i < N; i++) {
System.out.print(ans[i] + " " );
}
}
public static void main (String[] args) {
int N = 5 , Y = 10 ;
generatePermutation(N, Y);
}
}
|
Python3
def findValue(N, Y):
return min (N, Y + 1 - N)
def generatePermutation(N, Y):
ans = [ 0 for _ in range (N)]
if (Y < N or ( 2 * Y) > (N * (N + 1 ))):
print ( - 1 )
return
s = set ()
for i in range ( 1 , N + 1 ):
s.add(i)
for i in range ( 0 , N):
len = N - i
val = findValue( len , Y)
ans[i] = val
Y - = val
if (val in s):
s.remove(val)
for i in range (N - 1 , - 1 , - 1 ):
if (ans[i] = = ans[i - 1 ]):
ans[i] = list (s)[ 0 ]
s.remove(ans[i])
for i in ans:
print (i, end = " " )
print ()
if __name__ = = "__main__" :
N, Y = 5 , 10
generatePermutation(N, Y)
|
C#
using System;
using System.Collections.Generic;
using System.Linq;
class GFG{
static int findValue( int N, int Y)
{
return Math.Min(N, Y + 1 - N);
}
static void generatePermutation( int N, int Y)
{
int [] ans = new int [N];
if (Y < N || (2 * Y) > (N * (N + 1))) {
Console.Write(-1);
return ;
}
HashSet< int > s = new HashSet< int >();
for ( int i = 1; i <= N; i++) {
s.Add(i);
}
for ( int i = 0; i < N; i++) {
int len = N - i;
int val = findValue(len, Y);
ans[i] = val;
Y -= val;
if (s.Contains(val))
s.Remove(val);
}
for ( int i = N - 1; i > 0; i--) {
if (ans[i] == ans[i - 1]) {
ans[i] = s.First();
s.Remove(ans[i]);
}
}
for ( int i = 0; i < N; i++) {
Console.Write(ans[i] + " " );
}
}
static public void Main (){
int N = 5, Y = 10;
generatePermutation(N, Y);
}
}
|
Javascript
<script>
function findValue(N, Y)
{
return Math.min(N, Y + 1 - N);
}
function generatePermutation(N, Y)
{
let ans = new Array(N);
if (Y < N || (2 * Y) > (N * (N + 1))) {
document.write(-1, "</br>" );
return ;
}
let s = new Set();
for (let i = 1; i <= N; i++) {
s.add(i);
}
for (let i = 0; i <N; i++) {
let len = N - i;
let val = findValue(len, Y);
ans[i] = val;
Y -= val;
if (s.has(val))
s. delete (val);
}
for (let i = N - 1; i > 0; i--) {
if (ans[i] == ans[i - 1]) {
ans[i] = Array.from(s)[0]
s. delete (ans[i]);
}
}
for (let i of ans) {
document.write(i, " " );
}
document.write( "</N;>" );
}
let N = 5, Y = 10;
generatePermutation(N, Y);
</script>
|
Time Complexity: O(N * log N).
If we are using a set, we can make it O(N) by using two pointer technique.
Auxiliary Space: O(N)
Share your thoughts in the comments
Please Login to comment...