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 condition
Input: 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++
#include <bits/stdc++.h>
using namespace std;
bool ispos( int mid, int K, int X)
{
int temp;
if (mid <= K) {
temp = mid * (mid + 1) / 2;
}
else {
temp = K * (K + 1) / 2;
int f1 = K * (K - 1) / 2;
int f2 = 2 * K - 1 - mid;
int f3 = f2 * (f2 + 1) / 2;
temp += f1 - f3;
}
return X <= temp;
}
int findMinOp( int X, int K)
{
int low = 1, high = 2 * K - 1;
while (high - low > 1) {
int mid = (low + high) / 2;
if (ispos(mid, K, X)) {
high = mid;
}
else {
low = mid + 1;
}
}
if (ispos(low, K, X))
return low;
else if (ispos(high, K, X))
return high;
else
return -1;
}
int32_t main()
{
int X = 6, K = 4;
cout << findMinOp(X, K) << endl;
int X1 = 5, K1 = 2;
cout << findMinOp(X1, K1) << endl;
return 0;
}
|
Java
import java.util.*;
class Main {
static boolean isPos( int mid, int K, int X) {
int temp;
if (mid <= K) {
temp = mid * (mid + 1 ) / 2 ;
} else {
temp = K * (K + 1 ) / 2 ;
int f1 = K * (K - 1 ) / 2 ;
int f2 = 2 * K - 1 - mid;
int f3 = f2 * (f2 + 1 ) / 2 ;
temp += f1 - f3;
}
return X <= temp;
}
static int findMinOp( int X, int K) {
int low = 1 , high = 2 * K - 1 ;
while (high - low > 1 ) {
int mid = (low + high) / 2 ;
if (isPos(mid, K, X)) {
high = mid;
} else {
low = mid + 1 ;
}
}
if (isPos(low, K, X))
return low;
else if (isPos(high, K, X))
return high;
else
return - 1 ;
}
public static void main(String[] args) {
int X = 6 , K = 4 ;
System.out.println(findMinOp(X, K));
int X1 = 5 , K1 = 2 ;
System.out.println(findMinOp(X1, K1));
}
}
|
Python
def ispos(mid, K, X):
temp = 0
if mid < = K:
temp = mid * (mid + 1 ) / / 2
else :
temp = K * (K + 1 ) / / 2
f1 = K * (K - 1 ) / / 2
f2 = 2 * K - 1 - mid
f3 = f2 * (f2 + 1 ) / / 2
temp + = f1 - f3
return X < = temp
def findMinOp(X, K):
low, high = 1 , 2 * K - 1
while high - low > 1 :
mid = (low + high) / / 2
if ispos(mid, K, X):
high = mid
else :
low = mid + 1
if ispos(low, K, X):
return low
elif ispos(high, K, X):
return high
else :
return - 1
X, K = 6 , 4
print (findMinOp(X, K))
X1, K1 = 5 , 2
print (findMinOp(X1, K1))
|
C#
using System;
class Program
{
static bool IsPositive( int mid, int K, int X)
{
int temp;
if (mid <= K)
{
temp = mid * (mid + 1) / 2;
}
else
{
temp = K * (K + 1) / 2;
int f1 = K * (K - 1) / 2;
int f2 = 2 * K - 1 - mid;
int f3 = f2 * (f2 + 1) / 2;
temp += f1 - f3;
}
return X <= temp;
}
static int FindMinOp( int X, int K)
{
int low = 1, high = 2 * K - 1;
while (high - low > 1)
{
int mid = (low + high) / 2;
if (IsPositive(mid, K, X))
{
high = mid;
}
else
{
low = mid + 1;
}
}
if (IsPositive(low, K, X))
return low;
else if (IsPositive(high, K, X))
return high;
else
return -1;
}
static void Main()
{
int X = 6, K = 4;
Console.WriteLine(FindMinOp(X, K));
int X1 = 5, K1 = 2;
Console.WriteLine(FindMinOp(X1, K1));
}
}
|
Javascript
function ispos(mid, K, X) {
let temp;
if (mid <= K) {
temp = (mid * (mid + 1)) / 2;
} else {
temp = (K * (K + 1)) / 2;
const f1 = (K * (K - 1)) / 2;
const f2 = 2 * K - 1 - mid;
const f3 = (f2 * (f2 + 1)) / 2;
temp += f1 - f3;
}
return X <= temp;
}
function findMinOp(X, K) {
let low = 1,
high = 2 * K - 1;
while (high - low > 1) {
const mid = Math.floor((low + high) / 2);
if (ispos(mid, K, X)) {
high = mid;
} else {
low = mid + 1;
}
}
if (ispos(low, K, X)) return low;
else if (ispos(high, K, X)) return high;
else return -1;
}
const X = 6,
K = 4;
console.log(findMinOp(X, K));
const X1 = 5,
K1 = 2;
console.log(findMinOp(X1, K1));
|
Time Complexity: O(logK) Auxiliary Space: O(1)
|