Primer elemento mayor o igual a X en la suma de prefijos de N números usando Binary Lifting

Dada una array de N enteros y un número X. La tarea es encontrar el índice del primer elemento que es mayor o igual a X en sumas de prefijos de N números.

Ejemplos: 

Entrada: arr[] = { 2, 5, 7, 1, 6, 9, 12, 4, 6 } y x = 8 
Salida: la array de suma de 2 
prefijos formada es { 2, 7, 14, 15, 21, 30, 42, 46, 52}, por lo tanto, 14 es el número cuyo índice es 2

Entrada: arr[] = { 2, 5, 7, 1, 6, 9, 12, 4, 6 } y x = 30 
Salida: 5

Enfoque: el problema se puede resolver utilizando la función lower_bound en la búsqueda binaria . Pero en esta publicación, el problema se resolverá utilizando Binary-Lifting . En el levantamiento binario, un valor aumenta (o se eleva) en potencias de 2, comenzando con la potencia más alta posible de 2 (log (N)) hasta la potencia más baja (0). 

  • Inicialice position = 0 y configure cada bit de posición, desde el bit más significativo hasta el bit menos significativo.
  • Cada vez que un bit se establece en 1, el valor de la posición aumenta (o se eleva).
  • Mientras aumenta o eleva la posición, asegúrese de que la suma del prefijo hasta la posición sea menor que v.
  • Aquí, los bits log(N) son necesarios para todos los valores posibles de ‘posición’ (desde log(N)th hasta 0th bit).
  • Determine el valor del i-ésimo bit. Primero, verifique si establecer el i-ésimo bit no hará que la ‘posición’ sea mayor que N, que es el tamaño de la array. Antes de subir a la nueva ‘posición’, verifique que el valor en esa nueva ‘posición’ sea menor que X o no.
  • Si esta condición es verdadera, la posición de destino se encuentra por encima de la ‘posición’ + 2^i , pero por debajo de la ‘posición’ + 2^(i+1). Esto se debe a que si la posición de destino estaba por encima de ‘posición’ + 2^(i+1), entonces la posición ya se habría elevado en 2^(i+1) (esta lógica es similar a la elevación binaria en los árboles).
  • Si es falso, entonces el valor objetivo se encuentra entre ‘posición’ y ‘posición’ + 2^i , así que intente levantar con una potencia menor de 2. Finalmente, el ciclo terminará de tal manera que el valor en esa posición sea menor que X. Aquí, en esta pregunta, se pide el límite inferior. Entonces, devuelve ‘posición’ + 1 .

A continuación se muestra la implementación del enfoque anterior:  

C++

// CPP program to find lower_bound of x in
// prefix sums array using binary lifting.
#include <bits/stdc++.h>
using namespace std;
 
// function to make prefix sums array
void MakePreSum(int arr[], int presum[], int n)
{
    presum[0] = arr[0];
    for (int i = 1; i < n; i++)
        presum[i] = presum[i - 1] + arr[i];
}
 
// function to find lower_bound of x in
// prefix sums array using binary lifting.
int BinaryLifting(int presum[], int n, int x)
{
    // initialize position
    int pos = 0;
 
    // find log to the base 2 value of n.
    int LOGN = log2(n);
 
    // if x less than first number.
    if (x <= presum[0])
        return 0;
 
    // starting from most significant bit.
    for (int i = LOGN; i >= 0; i--) {
 
        // if value at this position less
        // than x then updateposition
        // Here (1<<i) is similar to 2^i.
        if (pos + (1 << i) < n &&
            presum[pos + (1 << i)] < x) {
            pos += (1 << i);
        }
    }
 
    // +1 because 'pos' will have position
    // of largest value less than 'x'
    return pos + 1;
}
 
// Driver code
int main()
{
    // given array
    int arr[] = { 2, 5, 7, 1, 6, 9, 12, 4, 6 };
 
    // value to find
    int x = 8;
 
    // size of array
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // to store prefix sum
    int presum[n] = { 0 };
 
    // call for prefix sum
    MakePreSum(arr, presum, n);
 
    // function call
    cout << BinaryLifting(presum, n, x);
 
    return 0;
}

Java

// Java program to find lower_bound of x in
// prefix sums array using binary lifting.
import java.util.*;
 
class solution
{
 
// function to make prefix sums array
static void MakePreSum(int []arr, int []presum, int n)
{
    presum[0] = arr[0];
    for (int i = 1; i < n; i++)
        presum[i] = presum[i - 1] + arr[i];
}
 
// function to find lower_bound of x in
// prefix sums array using binary lifting.
static int BinaryLifting(int []presum, int n, int x)
{
    // initialize position
    int pos = 0;
 
    // find log to the base 2 value of n.
    int LOGN = (int)Math.log(n);
 
    // if x less than first number.
    if (x <= presum[0])
        return 0;
 
    // starting from most significant bit.
    for (int i = LOGN; i >= 0; i--) {
 
        // if value at this position less
        // than x then updateposition
        // Here (1<<i) is similar to 2^i.
        if (pos + (1 << i) < n &&
            presum[pos + (1 << i)] < x) {
            pos += (1 << i);
        }
    }
 
    // +1 because 'pos' will have position
    // of largest value less than 'x'
    return pos + 1;
}
 
// Driver code
public static void main(String args[])
{
    // given array
    int []arr = { 2, 5, 7, 1, 6, 9, 12, 4, 6 };
 
    // value to find
    int x = 8;
 
    // size of array
    int n = arr.length;
 
    // to store prefix sum
    int []presum = new int[n];
    Arrays.fill(presum,0);
 
    // call for prefix sum
    MakePreSum(arr, presum, n);
 
    // function call
    System.out.println(BinaryLifting(presum, n, x));
 
}
 
}

Python 3

# Python 3 program to find
# lower_bound of x in prefix
# sums array using binary lifting.
import math
 
# function to make prefix
# sums array
def MakePreSum( arr, presum, n):
 
    presum[0] = arr[0]
    for i in range(1, n):
        presum[i] = presum[i - 1] + arr[i]
 
# function to find lower_bound of x in
# prefix sums array using binary lifting.
def BinaryLifting(presum, n, x):
 
    # initialize position
    pos = 0
 
    # find log to the base 2
    # value of n.
    LOGN = int(math.log2(n))
 
    # if x less than first number.
    if (x <= presum[0]):
        return 0
 
    # starting from most significant bit.
    for i in range(LOGN, -1, -1) :
 
        # if value at this position less
        # than x then updateposition
        # Here (1<<i) is similar to 2^i.
        if (pos + (1 << i) < n and
            presum[pos + (1 << i)] < x) :
            pos += (1 << i)
 
    # +1 because 'pos' will have position
    # of largest value less than 'x'
    return pos + 1
 
# Driver code
if __name__ == "__main__":
     
    # given array
    arr = [ 2, 5, 7, 1, 6,
            9, 12, 4, 6 ]
 
    # value to find
    x = 8
 
    # size of array
    n = len(arr)
 
    # to store prefix sum
    presum = [0] * n
 
    # call for prefix sum
    MakePreSum(arr, presum, n)
 
    # function call
    print(BinaryLifting(presum, n, x))
 
# This code is contributed
# by ChitraNayal

C#

// C# program to find lower_bound of x in
// prefix sums array using binary lifting.
using System;
 
class GFG
{
 
    // function to make prefix sums array
    static void MakePreSum(int []arr,
                    int []presum, int n)
    {
        presum[0] = arr[0];
        for (int i = 1; i < n; i++)
            presum[i] = presum[i - 1] + arr[i];
    }
 
    // function to find lower_bound of x in
    // prefix sums array using binary lifting.
    static int BinaryLifting(int []presum,
                            int n, int x)
    {
        // initialize position
        int pos = 0;
 
        // find log to the base 2 value of n.
        int LOGN = (int)Math.Log(n);
 
        // if x less than first number.
        if (x <= presum[0])
            return 0;
 
        // starting from most significant bit.
        for (int i = LOGN; i >= 0; i--)
        {
 
            // if value at this position less
            // than x then updateposition
            // Here (1<<i) is similar to 2^i.
            if (pos + (1 << i) < n &&
                presum[pos + (1 << i)] < x)
            {
                pos += (1 << i);
            }
        }
 
        // +1 because 'pos' will have position
        // of largest value less than 'x'
        return pos + 1;
    }
 
    // Driver code
    public static void Main()
    {
        // given array
        int []arr = { 2, 5, 7, 1, 6, 9, 12, 4, 6 };
 
        // value to find
        int x = 8;
 
        // size of array
        int n = arr.Length;
 
        // to store prefix sum
        int []presum = new int[n];
 
        // call for prefix sum
        MakePreSum(arr, presum, n);
 
        // function call
        Console.WriteLine(BinaryLifting(presum, n, x));
    }
}
 
// This code has been contributed
// by PrinciRaj1992

Javascript

<script>
 
// Javascript program to find lower_bound of x in
// prefix sums array using binary lifting.
 
     
    // function to make prefix sums array
    function MakePreSum(arr,presum,n)
    {
        presum[0] = arr[0];
    for (let i = 1; i < n; i++)
        presum[i] = presum[i - 1] + arr[i];
    }
 
   
// function to find lower_bound of x in
// prefix sums array using binary lifting.
function BinaryLifting(presum, n,k)
{
    // initialize position
    let pos = 0;
   
    // find log to the base 2 value of n.
    let LOGN = Math.log(n);
   
    // if x less than first number.
    if (x <= presum[0])
        return 0;
   
    // starting from most significant bit.
    for (let i = LOGN; i >= 0; i--) {
   
        // if value at this position less
        // than x then updateposition
        // Here (1<<i) is similar to 2^i.
        if (pos + (1 << i) < n &&
            presum[pos + (1 << i)] < x) {
            pos += (1 << i);
        }
    }
   
    // +1 because 'pos' will have position
    // of largest value less than 'x'
    return pos + 1;
}
 
// Driver code
 
// given array
let arr=[2, 5, 7, 1, 6, 9, 12, 4, 6];
// value to find
let x = 8;
 
// size of array
let n = arr.length;
 
// to store prefix sum
let presum = new Array(n);
for(let i=0;i<n;i++)
{
    presum[i]=0;
}
 
// call for prefix sum
MakePreSum(arr, presum, n);
 
// function call
document.write(BinaryLifting(presum, n, x));
   
     
// This code is contributed by avanitrachhadiya2155
 
</script>
Producción: 

2

 

Complejidad temporal: O(N) 
Espacio auxiliar: O(N)
 

Publicación traducida automáticamente

Artículo escrito por pawan_asipu y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *