Given integer X (1 <= X <= 1018) and integer K (1 <= K <= 109) representing sequence {1, 2, …, K – 2, K – 1, K, K – 1, K – 2, ….., 2, 1} of size 2 * K – 1, the task for this problem is to find minimum number of operations required to find sum at least X. In one operation remove the first element of the sequence and add it into sum then delete it from the sequence. If it is not possible print -1.
Examples:
Input: X = 6, K = 4
Output: 3
Explanation: For K = 4, the sequence is {1, 2, 3, 4, 3, 2, 1} Sum of the first 3 elements 1 + 2 + 3 >= X satisfies the conditionInput: X = 5, K = 2
Output: -1
Explanation: For K = 2, the sequence is {1, 2, 1} Even if we add all elements from the sequence then also sum of at least X can not be achieved therefore the answer will be -1
Approach: To solve the problem follow the below idea:
- Binary Search can be used to solve this problem and the range of binary search will be 1 to 2 * K – 1. f(n) is a monotonic function that represents whether sum X can be achieved with n operations or not. it is of the form FFFFFFFTTTTTTT. we have to find when the first time function becomes true using Binary Search.
- We have sequence 1 + 2 + ….. + K – 1 + K + K – 1 + K – 2 + …. + 3 + 2 + 1 to find the sum of the first mid elements we can define four variables temp, f1, f2, and f3.
- The first half will be the first K elements 1 + 2 + …. + K which can be found by the formula of the sum of first K natural numbers temp = K * (K + 1) / 2.
- The second half contains K – 1 + K – 2 + …… + 3 + 2 + 1 which can be found by the formula of the sum of first K – 1 natural numbers f1 = (K – 1) * K / 2
- f2 will store the number of elements to be removed from the suffix of the sequence to find sum of first mid elements of sequence f2 = 2 * K – 1 – mid
- f3 will store sum of last elements to be removed to form sum of first mid elements f3 = f2 * (f2 + 1) / 2
- Finally f1 – f3 is other half of sum temp += f1 – f3 (temp is sum of first mid elements of the sequence).
Below are the steps for the above approach:
- Set low and high range of binary search.
- ispos(mid) function used to check whether sum of first mid elements of sequence is at least X of not.
- Run while loop till high and low are not equal.
- In while loop find middle element and store it in mid variable.
- Check if that mid can be maximum value of array using ispos() function. If it is true then set high = mid else low = mid + 1.
- After loop ends if ispos() true for low then return low else check if it is true for high then return high else return -1.
Below is the implementation of the above approach:
// C++ code to implement the approach #include <bits/stdc++.h> using namespace std;
// Function to check if mid operations are // enough to remove at least X total // sum from sequence bool ispos( int mid, int K, int X)
{ // Declaring to calculate sum of
// first mid elements
int temp;
// if sum of first K elements are needed
if (mid <= K) {
temp = mid * (mid + 1) / 2;
}
else {
// Sum of first K elements
temp = K * (K + 1) / 2;
// Sum of remaining K - 1 elements
int f1 = K * (K - 1) / 2;
// We only want sum till mid
int f2 = 2 * K - 1 - mid;
// Sum of last f2 elements is
int f3 = f2 * (f2 + 1) / 2;
// Required sum is f1 - f3
temp += f1 - f3;
}
// If sum of first mid element is at least
// required X then return true else false
return X <= temp;
} // Function to find Minimum number of operations // for forming sum at least X by removing // elements from sequence int findMinOp( int X, int K)
{ // Range of binary search
int low = 1, high = 2 * K - 1;
// Running loop till high
// is not equal to low
while (high - low > 1) {
// mid is average of low and high
int mid = (low + high) / 2;
// Checking test function
if (ispos(mid, K, X)) {
high = mid;
}
else {
low = mid + 1;
}
}
// Checking whether low can be answer
if (ispos(low, K, X))
return low;
// If not then it is high
else if (ispos(high, K, X))
return high;
else
return -1;
} // Driver Code int32_t main() { // Input 1
int X = 6, K = 4;
// Function Call
cout << findMinOp(X, K) << endl;
// Input 2
int X1 = 5, K1 = 2;
// Function Call
cout << findMinOp(X1, K1) << endl;
return 0;
} |
// Java code to implement the approach import java.util.*;
class Main {
// Function to check if mid operations are
// enough to remove at least X total
// sum from sequence
static boolean isPos( int mid, int K, int X) {
// Declaring to calculate sum of
// first mid elements
int temp;
// if sum of first K elements are needed
if (mid <= K) {
temp = mid * (mid + 1 ) / 2 ;
} else {
// Sum of first K elements
temp = K * (K + 1 ) / 2 ;
// Sum of remaining K - 1 elements
int f1 = K * (K - 1 ) / 2 ;
// We only want sum till mid
int f2 = 2 * K - 1 - mid;
// Sum of last f2 elements is
int f3 = f2 * (f2 + 1 ) / 2 ;
// Required sum is f1 - f3
temp += f1 - f3;
}
// If sum of first mid element is at least
// required X then return true else false
return X <= temp;
}
// Function to find Minimum number of operations
// for forming sum at least X by removing
// elements from sequence
static int findMinOp( int X, int K) {
// Range of binary search
int low = 1 , high = 2 * K - 1 ;
// Running loop till high
// is not equal to low
while (high - low > 1 ) {
// mid is the average of low and high
int mid = (low + high) / 2 ;
// Checking test function
if (isPos(mid, K, X)) {
high = mid;
} else {
low = mid + 1 ;
}
}
// Checking whether low can be an answer
if (isPos(low, K, X))
return low;
// If not then it is high
else if (isPos(high, K, X))
return high;
else
return - 1 ;
}
// Driver Code
public static void main(String[] args) {
// Input 1
int X = 6 , K = 4 ;
// Function Call
System.out.println(findMinOp(X, K));
// Input 2
int X1 = 5 , K1 = 2 ;
// Function Call
System.out.println(findMinOp(X1, K1));
}
} //this code is contributed by uttamdp_10 |
# Function to check if mid operations are # enough to remove at least X total # sum from sequence def ispos(mid, K, X):
# Declaring to calculate sum of
# first mid elements
temp = 0
# if sum of first K elements are needed
if mid < = K:
temp = mid * (mid + 1 ) / / 2
else :
# Sum of first K elements
temp = K * (K + 1 ) / / 2
# Sum of remaining K - 1 elements
f1 = K * (K - 1 ) / / 2
# We only want sum till mid
f2 = 2 * K - 1 - mid
# Sum of last f2 elements is
f3 = f2 * (f2 + 1 ) / / 2
# Required sum is f1 - f3
temp + = f1 - f3
# If sum of first mid element is at least
# required X then return true else false
return X < = temp
# Function to find Minimum number of operations # for forming sum at least X by removing # elements from sequence def findMinOp(X, K):
# Range of binary search
low, high = 1 , 2 * K - 1
# Running loop till high
# is not equal to low
while high - low > 1 :
# mid is average of low and high
mid = (low + high) / / 2
# Checking test function
if ispos(mid, K, X):
high = mid
else :
low = mid + 1
# Checking whether low can be answer
if ispos(low, K, X):
return low
# If not then it is high
elif ispos(high, K, X):
return high
else :
return - 1
# Driver Code # Input 1 X, K = 6 , 4
# Function Call print (findMinOp(X, K))
# Input 2 X1, K1 = 5 , 2
# Function Call print (findMinOp(X1, K1))
|
using System;
class Program
{ // Function to check if mid operations are
// enough to remove at least X total
// sum from sequence
static bool IsPositive( int mid, int K, int X)
{
// Declaring to calculate sum of
// first mid elements
int temp;
// if sum of first K elements are needed
if (mid <= K)
{
temp = mid * (mid + 1) / 2;
}
else
{
// Sum of first K elements
temp = K * (K + 1) / 2;
// Sum of remaining K - 1 elements
int f1 = K * (K - 1) / 2;
// We only want sum till mid
int f2 = 2 * K - 1 - mid;
// Sum of last f2 elements is
int f3 = f2 * (f2 + 1) / 2;
// Required sum is f1 - f3
temp += f1 - f3;
}
// If sum of first mid element is at least
// required X then return true else false
return X <= temp;
}
// Function to find Minimum number of operations
// for forming sum at least X by removing
// elements from sequence
static int FindMinOp( int X, int K)
{
// Range of binary search
int low = 1, high = 2 * K - 1;
// Running loop till high
// is not equal to low
while (high - low > 1)
{
// mid is average of low and high
int mid = (low + high) / 2;
// Checking test function
if (IsPositive(mid, K, X))
{
high = mid;
}
else
{
low = mid + 1;
}
}
// Checking whether low can be answer
if (IsPositive(low, K, X))
return low;
// If not then it is high
else if (IsPositive(high, K, X))
return high;
else
return -1;
}
// Driver Code
static void Main()
{
// Input 1
int X = 6, K = 4;
// Function Call
Console.WriteLine(FindMinOp(X, K));
// Input 2
int X1 = 5, K1 = 2;
// Function Call
Console.WriteLine(FindMinOp(X1, K1));
}
} |
// Javascript code to implement the approach // Function to check if mid operations are // enough to remove at least X total // sum from sequence function ispos(mid, K, X) {
// Declaring to calculate sum of
// first mid elements
let temp;
// if sum of first K elements are needed
if (mid <= K) {
temp = (mid * (mid + 1)) / 2;
} else {
// Sum of first K elements
temp = (K * (K + 1)) / 2;
// Sum of remaining K - 1 elements
const f1 = (K * (K - 1)) / 2;
// We only want sum till mid
const f2 = 2 * K - 1 - mid;
// Sum of last f2 elements is
const f3 = (f2 * (f2 + 1)) / 2;
// Required sum is f1 - f3
temp += f1 - f3;
}
// If sum of first mid element is at least
// required X then return true else false
return X <= temp;
} // Function to find Minimum number of operations // for forming sum at least X by removing // elements from sequence function findMinOp(X, K) {
// Range of binary search
let low = 1,
high = 2 * K - 1;
// Running loop till high
// is not equal to low
while (high - low > 1) {
// mid is average of low and high
const mid = Math.floor((low + high) / 2);
// Checking test function
if (ispos(mid, K, X)) {
high = mid;
} else {
low = mid + 1;
}
}
// Checking whether low can be answer
if (ispos(low, K, X)) return low;
// If not then it is high
else if (ispos(high, K, X)) return high;
else return -1;
} // Driver Code // Input 1 const X = 6, K = 4;
// Function Call console.log(findMinOp(X, K)); // Input 2 const X1 = 5, K1 = 2;
// Function Call console.log(findMinOp(X1, K1)); |
3 -1
Time Complexity: O(logK)
Auxiliary Space: O(1)