Open In App

Min Operations for Target Sum in Special Sequence

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:

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));

Output
3
-1


Time Complexity: O(logK)
Auxiliary Space: O(1)


Article Tags :