给定一个n个元素的数组,任务是找到该数组的一个子集的斐波那契总和,其中子集的每个元素<= k。
精确地找到F(A i 1 )+ F(A i 2 )+ F(A i 3 )+…+ F(A i x )) ,其中(A i 1 ,A i 2 ,…,A i x ) <= K和1 <=(i 1 ,i 2 ,…,i x )<= n。 F(i)是第i个斐波那契数
例子 :
Input : arr = {1, 2, 3, 4, 2, 7}
Query 1 : K = 2
Query 2 : K = 6
Output : 3
8
解释 :
在查询1中,子集{1、2、2}是这样的子集,其中子集中的所有元素均<= k,在这种情况下为<= 2。子集的斐波那契总和= F(1)+ F(2)+ F(2)= 1 +1 + 1 = 3
在查询2中,子集{1、2、3、4、2}是这样的子集,其中子集中的所有元素均<= k,在这种情况下为<= 6。子集的斐波那契总和= F(1)+ F(2)+ F(3)+ F(4)+ F(2)= 1 +1 + 2 + 3 +1 = 8
使用两种不同的查询技术来解决此问题,即:
1)在线查询
2)离线查询
在这两种方法中,唯一的共同的步骤是第n个斐波纳契number.For的有效技术来产生使用该第Fibonacci数的n的产生。
产生斐波那契数的这种方法是两种查询技术所共有的。现在,看看如何使用通过这两种技术中的每一种生成的斐波那契数。
方法1(在线查询):
用这种技术,在查询到达时对其进行处理。首先,按升序对数组进行排序。查询特定的k后,对该排序后的数组使用二进制搜索,以找到该数组的值为&<= k的最后一个索引。我们将此位置称为x。
现在,由于数组已排序,
For all i <= x, a[i] <= x
i.e
a[i] <= a[x] for all i ∈ [1, x]
因此,要关注的子集是排序后的数组A中的A 1 ,A 2 ,A 3 ,…. A x ,斐波那契和为: F(A 1 )+ F(A 2 )+ F(A 3 )+ …+ F(A x )
使用前缀求和数组可以有效地找到子集A 1 ,A 2 ,A 3 ,…. A x的总和。
如果prefixFibSum [i]存储斐波那契和,直到已排序数组A的第i个索引,则数组子集从1到x的斐波那契和为prefixFibSum [x]
因此,子集[1…x]的斐波那契总和= prefixFibSum [x] ,prefixFibSum [x]可以计算如下:
prefixFibSum [X] = prefixFibSum [X – 1] + A [X]第斐波那契数,其中,A [x]表示在阵列的第x个索引的数组元素。
C++
// C++ program to find fibonacci sum of
// subarray where all elements <= k
#include
using namespace std;
// Helper function that multiplies 2 matrices
// F and M of size 2*2, and puts the multiplication
// result back to F[][]
void multiply(int F[2][2], int M[2][2])
{
int x = F[0][0] * M[0][0] + F[0][1] * M[1][0];
int y = F[0][0] * M[0][1] + F[0][1] * M[1][1];
int z = F[1][0] * M[0][0] + F[1][1] * M[1][0];
int w = F[1][0] * M[0][1] + F[1][1] * M[1][1];
F[0][0] = x;
F[0][1] = y;
F[1][0] = z;
F[1][1] = w;
}
/* Helper function that calculates F[][]
raise to the power n and puts the
result in F[][] */
void power(int F[2][2], int n)
{
int i;
int M[2][2] = { { 1, 1 }, { 1, 0 } };
// n - 1 times multiply the
// matrix to {{1, 0}, {0, 1}}
for (i = 2; i <= n; i++)
multiply(F, M);
}
// Returns the nth fibonacci number
int fib(int n)
{
int F[2][2] = { { 1, 1 }, { 1, 0 } };
if (n == 0)
return 0;
power(F, n - 1);
return F[0][0];
}
int findLessThanK(int arr[], int n, int k)
{
// find first index which is > k
// using lower_bound
return (lower_bound(arr, arr + n, k + 1)
- arr);
}
// Function to build Prefix Fibonacci Sum
int* buildPrefixFibonacciSum(int arr[], int n)
{
// Allocate memory to prefix
// fibonacci sum array
int* prefixFibSum = new int[n];
// Traverse the array from 0 to n - 1,
// when at the ith index then we calculate
// the a[i]th fibonacci number and calculate
// the fibonacci sum till the ith index as
// the sum of fibonacci sum till index i - 1
// and the a[i]th fibonacci number
for (int i = 0; i < n; i++)
{
int currFibNumber = fib(arr[i]);
if (i == 0) {
prefixFibSum[i] = currFibNumber;
}
else {
prefixFibSum[i] = prefixFibSum[i - 1]
+ currFibNumber;
}
}
return prefixFibSum;
}
// Return the answer for each query
int processQuery(int arr[], int prefixFibSum[],
int n, int k)
{
// index stores the index till where
// the array elements are less than k
int lessThanIndex = findLessThanK(arr, n, k);
if (lessThanIndex == 0)
return 0;
return prefixFibSum[lessThanIndex - 1];
}
// Driver Code
int main()
{
int arr[] = { 1, 2, 3, 4, 2, 7 };
int n = sizeof(arr) / sizeof(arr[0]);
// sort the array arr
sort(arr, arr + n);
// Build the prefix fibonacci sum array
int* prefixFibSum =
buildPrefixFibonacciSum(arr, n);
// query array stores q queries
int query[] = { 2, 6 };
int q = sizeof(query) / sizeof(query[0]);
for (int i = 0; i < q; i++) {
int k = query[i];
int ans =
processQuery(arr, prefixFibSum, n, k);
cout << "Query " << i + 1 << " : "
<< ans << endl;
}
return 0;
}
Java
// Java program to find fibonacci sum of
// subarray where all elements <= k
import java.util.*;
class GFG
{
// Helper function that multiplies 2 matrices
// F and M of size 2*2, and puts the multiplication
// result back to F[][]
static void multiply(int[][] F, int[][] M)
{
int x = F[0][0] * M[0][0] + F[0][1] * M[1][0];
int y = F[0][0] * M[0][1] + F[0][1] * M[1][1];
int z = F[1][0] * M[0][0] + F[1][1] * M[1][0];
int w = F[1][0] * M[0][1] + F[1][1] * M[1][1];
F[0][0] = x;
F[0][1] = y;
F[1][0] = z;
F[1][1] = w;
}
/*
* Helper function that calculates F[][]
raise to the power n and puts the
* result in F[][]
*/
static void power(int[][] F, int n)
{
int i;
int[][] M = { { 1, 1 }, { 1, 0 } };
// n - 1 times multiply the
// matrix to {{1, 0}, {0, 1}}
for (i = 2; i <= n; i++)
multiply(F, M);
}
// Returns the nth fibonacci number
static int fib(int n)
{
int[][] F = { { 1, 1 }, { 1, 0 } };
if (n == 0)
return 0;
power(F, n - 1);
return F[0][0];
}
static int findLessThanK(int arr[], int n, int k)
{
// find first index which is > k
// using lower_bound
return (lower_bound(arr, 0, n, k + 1));
}
static int lower_bound(int[] a, int low,
int high, int element)
{
while (low < high)
{
int middle = low + (high - low) / 2;
if (element > a[middle])
low = middle + 1;
else
high = middle;
}
return low;
}
// Function to build Prefix Fibonacci Sum
static int[] buildPrefixFibonacciSum(int arr[], int n)
{
// Allocate memory to prefix
// fibonacci sum array
int[] prefixFibSum = new int[n];
// Traverse the array from 0 to n - 1,
// when at the ith index then we calculate
// the a[i]th fibonacci number and calculate
// the fibonacci sum till the ith index as
// the sum of fibonacci sum till index i - 1
// and the a[i]th fibonacci number
for (int i = 0; i < n; i++)
{
int currFibNumber = fib(arr[i]);
if (i == 0)
{
prefixFibSum[i] = currFibNumber;
}
else
{
prefixFibSum[i] = prefixFibSum[i - 1] +
currFibNumber;
}
}
return prefixFibSum;
}
// Return the answer for each query
static int processQuery(int arr[], int prefixFibSum[],
int n, int k)
{
// index stores the index till where
// the array elements are less than k
int lessThanIndex = findLessThanK(arr, n, k);
if (lessThanIndex == 0)
return 0;
return prefixFibSum[lessThanIndex - 1];
}
// Driver Code
public static void main(String[] args)
{
int arr[] = { 1, 2, 3, 4, 2, 7 };
int n = arr.length;
// sort the array arr
Arrays.sort(arr);
// Build the prefix fibonacci sum array
int[] prefixFibSum = buildPrefixFibonacciSum(arr, n);
// query array stores q queries
int query[] = { 2, 6 };
int q = query.length;
for (int i = 0; i < q; i++)
{
int k = query[i];
int ans = processQuery(arr, prefixFibSum, n, k);
System.out.print("Query " + (i + 1) + " : " + ans + "\n");
}
}
}
// This code is contributed by Rajput-Ji
C#
// C# program to find fibonacci sum of
// subarray where all elements <= k
using System;
class GFG
{
// Helper function that multiplies 2 matrices
// F and M of size 2*2, and puts the multiplication
// result back to F[,]
static void multiply(int[,] F, int[,] M)
{
int x = F[0, 0] * M[0, 0] + F[0, 1] * M[1, 0];
int y = F[0, 0] * M[0, 1] + F[0, 1] * M[1, 1];
int z = F[1, 0] * M[0, 0] + F[1, 1] * M[1, 0];
int w = F[1, 0] * M[0, 1] + F[1, 1] * M[1, 1];
F[0, 0] = x;
F[0, 1] = y;
F[1, 0] = z;
F[1, 1] = w;
}
/*
* Helper function that calculates F[,]
raise to the power n and puts the
* result in F[,]
*/
static void power(int[,] F, int n)
{
int i;
int[,] M = { { 1, 1 }, { 1, 0 } };
// n - 1 times multiply the
// matrix to {{1, 0}, {0, 1}}
for (i = 2; i <= n; i++)
multiply(F, M);
}
// Returns the nth fibonacci number
static int fib(int n)
{
int[,] F = {{ 1, 1 }, { 1, 0 }};
if (n == 0)
return 0;
power(F, n - 1);
return F[0, 0];
}
static int findLessThanK(int []arr, int n, int k)
{
// find first index which is > k
// using lower_bound
return (lower_bound(arr, 0, n, k + 1));
}
static int lower_bound(int[] a, int low,
int high, int element)
{
while (low < high)
{
int middle = low + (high - low) / 2;
if (element > a[middle])
low = middle + 1;
else
high = middle;
}
return low;
}
// Function to build Prefix Fibonacci Sum
static int[] buildPrefixFibonacciSum(int []arr, int n)
{
// Allocate memory to prefix
// fibonacci sum array
int[] prefixFibSum = new int[n];
// Traverse the array from 0 to n - 1,
// when at the ith index then we calculate
// the a[i]th fibonacci number and calculate
// the fibonacci sum till the ith index as
// the sum of fibonacci sum till index i - 1
// and the a[i]th fibonacci number
for (int i = 0; i < n; i++)
{
int currFibNumber = fib(arr[i]);
if (i == 0)
{
prefixFibSum[i] = currFibNumber;
}
else
{
prefixFibSum[i] = prefixFibSum[i - 1] +
currFibNumber;
}
}
return prefixFibSum;
}
// Return the answer for each query
static int processQuery(int []arr, int []prefixFibSum,
int n, int k)
{
// index stores the index till where
// the array elements are less than k
int lessThanIndex = findLessThanK(arr, n, k);
if (lessThanIndex == 0)
return 0;
return prefixFibSum[lessThanIndex - 1];
}
// Driver Code
public static void Main(String[] args)
{
int []arr = { 1, 2, 3, 4, 2, 7 };
int n = arr.Length;
// sort the array arr
Array.Sort(arr);
// Build the prefix fibonacci sum array
int[] prefixFibSum = buildPrefixFibonacciSum(arr, n);
// query array stores q queries
int []query = {2, 6};
int q = query.Length;
for (int i = 0; i < q; i++)
{
int k = query[i];
int ans = processQuery(arr, prefixFibSum, n, k);
Console.Write("Query " + (i + 1) + " : " + ans + "\n");
}
}
}
// This code is contributed by PrinciRaj1992
Query 1 : 3
Query 2 : 8
时间复杂度: O(nlogn + qlogn)
方法2(离线查询):
在脱机查询中,存储查询并以特定顺序计算每个查询的答案,并以原始指定顺序存储和输出查询结果。
将每个查询存储为一对整数,其中该对的第一个成员是该查询的查询参数K,该对的第二个成员是该查询最初发生的索引。
例如,如果查询如下:
查询1:K = 13;
查询2:K = 3;
查询3:K = 8;
然后,存储查询1为其中13是K的针对该查询的值和1是指定它是第1次的查询,类似于查询2和查询3被表示为分别的索引。
一次,所有单个查询都表示为整数对,并基于K以递增的方式对查询对数组进行排序。
例如,上面的查询在排序后看起来像{,,}。
排序查询背后的想法:
对查询进行排序的主要思想是,对于某个查询q i ,当子集中的元素小于k时,则对于所有查询q j ,其中i
j,指向查询数组的第j个索引
然后,考虑以下伪代码:
while (i <= query[j].K) {
fibonacciSum = fibonacciSum + a[i]th Fibonacci number
i = i + 1
}
因此,虽然子集中的元素小于或等于当前查询对的第一个成员(即K),但继续前进到下一个元素,同时将所需的斐波那契数加到当前总和上。一旦当前元素大于当前查询的参数K,就将当前和的当前值存储在名为q的ans的辅助数组中(即查询数),位于当前查询对的第二个成员所指向的索引处(即发生当前查询的原始索引)。
ans[query[j].original index] = current value of fibonacciSum
最后,打印ans数组,该数组按最初出现的顺序存储所有查询的结果。
// C++ program to find fibonacci sum of
// subarray where all elements <= k
#include
using namespace std;
// structure where K is the query parameter
// and original index is the index where the
// query was originally present at.
struct offlineQuery {
int K, originalIndex;
};
// function tp compare queries
bool cmp(offlineQuery q1, offlineQuery q2)
{
return q1.K < q2.K;
}
/* Helper function that multiplies 2 matrices
F and M of size 2*2, and puts the multiplication
result back to F[][] */
void multiply(int F[2][2], int M[2][2])
{
int x = F[0][0] * M[0][0] + F[0][1] * M[1][0];
int y = F[0][0] * M[0][1] + F[0][1] * M[1][1];
int z = F[1][0] * M[0][0] + F[1][1] * M[1][0];
int w = F[1][0] * M[0][1] + F[1][1] * M[1][1];
F[0][0] = x;
F[0][1] = y;
F[1][0] = z;
F[1][1] = w;
}
/* Helper function that calculates F[][] raise
to the power n and puts the result in F[][] */
void power(int F[2][2], int n)
{
int i;
int M[2][2] = { { 1, 1 }, { 1, 0 } };
// n - 1 times multiply the
// matrix to {{1, 0}, {0, 1}}
for (i = 2; i <= n; i++)
multiply(F, M);
}
// Returns the nth fibonacci number
int fib(int n)
{
int F[2][2] = { { 1, 1 }, { 1, 0 } };
if (n == 0)
return 0;
power(F, n - 1);
return F[0][0];
}
// Return the answer for each query
int* processQuery(int arr[], int queries[],
int n, int q)
{
// build offline queries where each query
// is of type offlineQuery which stores
// both K and original Index of the query
// in the queries array
offlineQuery* offlineQueries =
new offlineQuery[q];
// Allocate memory to store ans of each query
int* ans = new int[q];
for (int i = 0; i < q; i++) {
int original_index = i;
int K = queries[i];
offlineQueries[i].K = K;
offlineQueries[i].originalIndex =
original_index;
}
// sort offlineQueries[]
sort(offlineQueries, offlineQueries + q, cmp);
// i is pointing to the current position
// array arr fibonacciSum store the
// fibonacciSum till ith index
int i = 0, fibonacciSum = 0;
for (int j = 0; j < q; j++)
{
int currK = offlineQueries[j].K;
int currQueryIndex =
offlineQueries[j].originalIndex;
// keep insering elements to subset
// while elements are less than
// current query's K value
while (i < n && arr[i] <= currK)
{
fibonacciSum += fib(arr[i]);
i++;
}
// store the current value of
// fibonacci sum in the array ans
// which stores results for the
// queries in the original order
ans[currQueryIndex] = fibonacciSum;
}
return ans;
}
// Driver Code
int main()
{
int arr[] = { 1, 2, 3, 4, 2, 7 };
int n = sizeof(arr) / sizeof(arr[0]);
// sort the array arr
sort(arr, arr + n);
// query array stores q queries
int queries[] = { 2, 10, 6 };
int q = sizeof(queries) / sizeof(queries[0]);
// res stores the result of each query
int* res = processQuery(arr, queries, n, q);
for (int i = 0; i < q; i++) {
int ans = res[i];
cout << "Query " << i + 1 << " : "
<< ans << endl;
}
return 0;
}
Query 1 : 3
Query 2 : 21
Query 3 : 8
时间复杂度: O(nlogn + qlogq)
如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。