Hollie  Ratke

Hollie Ratke

1603803600

Maximum subsequence sum obtained by concatenating disjoint subarrays

Given an array arr[] of size **N, **the task is to find the maximum sum of a subsequence formed by concatenating disjoint subarrays whose lengths are prime numbers.

Examples:

Input:_ arr[] = {10, 10, 7, 10, 10, 10}_

Output:_ 50_

Explanation:

Subsequence with maximum sum is obtained by concatenating following two subarrays:

  1. {10, 10} of length 2, which is prime.
  2. {10, 10, 10} of length 3, which is prime.

The resulting subsequence is {10, 10, 10, 10, 10}.

Sum of the subsequence is 50.

Input:_ arr[] = {11, 8, 12}_

Output:_ 31_

Naive Approach: The simplest approach is to use recursion to calculate the value of the maximum sum of subsequence. In each step, call multiple recursive calls for each of the prime numbers smaller than N. The recurrence relation is given by:

sum(N) = (arr[N] + arr[N – 1] + … arr[N – P + 1]) + sum(N – P – 1)

where,

P is the prime length of the subarray chosen,

sum(N) is the function that finds the maximum sum of resulting subsequence.

The above recurrence relation is for only one Prime Number. Therefore, there can be more than one possible subsequence can be formed by selecting different subarrays of different prime length. Below is the resulting recurrence relation formed:

sum(N) = max(sum(aN, …, aN-P1+1) + sum(N – P1 – 1), sum(aN, …, aN-P2+1) + sum(N – P2 – 1), …, sum(aN, …, aN-Pk+1) + sum(N – Pk – 1))

where,

P1, P2, … Pk are prime numbers smaller than N.

Time Complexity:_ O(KN) where K is the number of _the _prime numbers smaller than N. Approximately K = (N / LogN) _

Auxiliary Space: O(1)

Dynamic Programming **using Bottom-up Approach: **The recursive calls in the above can also be reduced using an auxiliary array dp[] and calculate the value of each state in the bottom-up approach. Below are the steps:

  • Create an auxiliary array prime[] to store all the prime numbers smaller or equal to N.
  • Maintain the Sieve of Eratosthenes and traverse it to populate the values of array prime[].
  • Create an auxiliary array** dp[] **of size N.
  • Initialize the state 0 and 1 as dp[0] = 0 and dp[1] = 0.
  • Traverse the array dp[] over the range** [2, N]** and update each state as:

_ MSS(i) = max[sum(ai…ai-P1+1) + sum(i-P1-1), sum(ai…ai-P2+1) + sum(i-P2-1), … sum(ai…ai-Pk+1) + sum(i-Pk-1) ] for all prime numbers P1, P2, … Pk smaller than N._

  • Initialize pref[] array to store prefix sum to calculate sum(l, …, r) efficiently.

ai + ai+1 + … aj = sum(i … j) = pref[j] – pref[i – 1]

  • Print the value of dp[N] after the above steps as the result.

Below is the implementation of the above approach:

  • C++

// C++ program for the above approach

#include <bits/stdc++.h>

**using** **namespace** std;

#define MAX 100005

// Function to return all prime numbers

// smaller than N

vector<``**int**``> SieveOfEratosthenes()

{

// Create a boolean array "prime[0..n]"

**bool** seive[MAX];

// Initialize all its entries as true

**memset**``(seive, **true**``, **sizeof**``(seive));

**for** (``**int** p = 2; p * p < MAX; p++) {

// If prime[p] is not changed,

// then it is a prime

**if** (seive[p] == **true**``) {

// Update all multiples of

// p greater than or equal

// to the square of it

**for** (``**int** i = p * p;

i < MAX; i += p) {

seive[i] = **false**``;

}

}

}

// Stores all prime numbers

// smaller than MAX

vector<``**int**``> v;

// Store all prime numbers

**for** (``**int** p = 2; p < MAX; p++) {

// If p is prime

**if** (seive[p]) {

v.push_back(p);

}

}

**return** v;

}

// Function to build the auxiliary DP

// array from the start

**void** build(``**int** dp[], **int** arr[], **int** N)

{

// Base Case

dp[0] = 0;

dp[1] = 0;

// Stores all prime numbers < N

vector<``**int**``> prime

= SieveOfEratosthenes();

// Stores prefix sum

**int** pref[N + 1];

pref[0] = 0;

// Update prefix sum

**for** (``**int** i = 1; i <= N; i++) {

pref[i] = pref[i - 1]

+ arr[i - 1];

}

// Iterate over range

**for** (``**int** i = 2; i <= N; i++) {

// Update each state i.e.. when

// current element is excluded

dp[i] = dp[i - 1];

**for** (``**int** j = 0;

j <= prime.size(); j++) {

// Find start & end index

// of subarrays when prime[i]

// is taken

**int** r = i - 1;

**int** l = r - prime[j] + 1;

// Check if starting point

// lies in the array

**if** (l < 0)

**break**``;

**int** temp = 0;

// Include the elements

// al al+1 ... ar

temp = pref[r + 1] - pref[l];

// Check if element lies before

// start of selected subarray

**if** (l - 2 >= 0)

temp += dp[l - 2 + 1];

// Update value of dp[i]

dp[i] = max(dp[i], temp);

}

}

}

// Function to find the maximum sum

// subsequence with prime length

**void** maxSumSubseq(``**int** arr[], **int** N)

{

// Auxiliary DP array

**int** dp[N + 1];

// Build DP array

build(dp, arr, N);

// Print the result

cout << dp[N];

}

// Driver Code

**int** main()

{

// Given arr[]

**int** arr[] = { 10, 10, 7, 10, 10, 10 };

// Size of array

**int** N = **sizeof**``(arr) / **sizeof**``(arr[0]);

// Function Call

maxSumSubseq(arr, N);

**return** 0;

}

Output:

50

Time Complexity:_ O(N * K)_

Auxiliary Space:_ O(N)_

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.

#arrays #dynamic programming #recursion #prefix-sum #prime number #sieve #subarray #subsequence

What is GEEK

Buddha Community

Maximum subsequence sum obtained by concatenating disjoint subarrays
Hollie  Ratke

Hollie Ratke

1603803600

Maximum subsequence sum obtained by concatenating disjoint subarrays

Given an array arr[] of size **N, **the task is to find the maximum sum of a subsequence formed by concatenating disjoint subarrays whose lengths are prime numbers.

Examples:

Input:_ arr[] = {10, 10, 7, 10, 10, 10}_

Output:_ 50_

Explanation:

Subsequence with maximum sum is obtained by concatenating following two subarrays:

  1. {10, 10} of length 2, which is prime.
  2. {10, 10, 10} of length 3, which is prime.

The resulting subsequence is {10, 10, 10, 10, 10}.

Sum of the subsequence is 50.

Input:_ arr[] = {11, 8, 12}_

Output:_ 31_

Naive Approach: The simplest approach is to use recursion to calculate the value of the maximum sum of subsequence. In each step, call multiple recursive calls for each of the prime numbers smaller than N. The recurrence relation is given by:

sum(N) = (arr[N] + arr[N – 1] + … arr[N – P + 1]) + sum(N – P – 1)

where,

P is the prime length of the subarray chosen,

sum(N) is the function that finds the maximum sum of resulting subsequence.

The above recurrence relation is for only one Prime Number. Therefore, there can be more than one possible subsequence can be formed by selecting different subarrays of different prime length. Below is the resulting recurrence relation formed:

sum(N) = max(sum(aN, …, aN-P1+1) + sum(N – P1 – 1), sum(aN, …, aN-P2+1) + sum(N – P2 – 1), …, sum(aN, …, aN-Pk+1) + sum(N – Pk – 1))

where,

P1, P2, … Pk are prime numbers smaller than N.

Time Complexity:_ O(KN) where K is the number of _the _prime numbers smaller than N. Approximately K = (N / LogN) _

Auxiliary Space: O(1)

Dynamic Programming **using Bottom-up Approach: **The recursive calls in the above can also be reduced using an auxiliary array dp[] and calculate the value of each state in the bottom-up approach. Below are the steps:

  • Create an auxiliary array prime[] to store all the prime numbers smaller or equal to N.
  • Maintain the Sieve of Eratosthenes and traverse it to populate the values of array prime[].
  • Create an auxiliary array** dp[] **of size N.
  • Initialize the state 0 and 1 as dp[0] = 0 and dp[1] = 0.
  • Traverse the array dp[] over the range** [2, N]** and update each state as:

_ MSS(i) = max[sum(ai…ai-P1+1) + sum(i-P1-1), sum(ai…ai-P2+1) + sum(i-P2-1), … sum(ai…ai-Pk+1) + sum(i-Pk-1) ] for all prime numbers P1, P2, … Pk smaller than N._

  • Initialize pref[] array to store prefix sum to calculate sum(l, …, r) efficiently.

ai + ai+1 + … aj = sum(i … j) = pref[j] – pref[i – 1]

  • Print the value of dp[N] after the above steps as the result.

Below is the implementation of the above approach:

  • C++

// C++ program for the above approach

#include <bits/stdc++.h>

**using** **namespace** std;

#define MAX 100005

// Function to return all prime numbers

// smaller than N

vector<``**int**``> SieveOfEratosthenes()

{

// Create a boolean array "prime[0..n]"

**bool** seive[MAX];

// Initialize all its entries as true

**memset**``(seive, **true**``, **sizeof**``(seive));

**for** (``**int** p = 2; p * p < MAX; p++) {

// If prime[p] is not changed,

// then it is a prime

**if** (seive[p] == **true**``) {

// Update all multiples of

// p greater than or equal

// to the square of it

**for** (``**int** i = p * p;

i < MAX; i += p) {

seive[i] = **false**``;

}

}

}

// Stores all prime numbers

// smaller than MAX

vector<``**int**``> v;

// Store all prime numbers

**for** (``**int** p = 2; p < MAX; p++) {

// If p is prime

**if** (seive[p]) {

v.push_back(p);

}

}

**return** v;

}

// Function to build the auxiliary DP

// array from the start

**void** build(``**int** dp[], **int** arr[], **int** N)

{

// Base Case

dp[0] = 0;

dp[1] = 0;

// Stores all prime numbers < N

vector<``**int**``> prime

= SieveOfEratosthenes();

// Stores prefix sum

**int** pref[N + 1];

pref[0] = 0;

// Update prefix sum

**for** (``**int** i = 1; i <= N; i++) {

pref[i] = pref[i - 1]

+ arr[i - 1];

}

// Iterate over range

**for** (``**int** i = 2; i <= N; i++) {

// Update each state i.e.. when

// current element is excluded

dp[i] = dp[i - 1];

**for** (``**int** j = 0;

j <= prime.size(); j++) {

// Find start & end index

// of subarrays when prime[i]

// is taken

**int** r = i - 1;

**int** l = r - prime[j] + 1;

// Check if starting point

// lies in the array

**if** (l < 0)

**break**``;

**int** temp = 0;

// Include the elements

// al al+1 ... ar

temp = pref[r + 1] - pref[l];

// Check if element lies before

// start of selected subarray

**if** (l - 2 >= 0)

temp += dp[l - 2 + 1];

// Update value of dp[i]

dp[i] = max(dp[i], temp);

}

}

}

// Function to find the maximum sum

// subsequence with prime length

**void** maxSumSubseq(``**int** arr[], **int** N)

{

// Auxiliary DP array

**int** dp[N + 1];

// Build DP array

build(dp, arr, N);

// Print the result

cout << dp[N];

}

// Driver Code

**int** main()

{

// Given arr[]

**int** arr[] = { 10, 10, 7, 10, 10, 10 };

// Size of array

**int** N = **sizeof**``(arr) / **sizeof**``(arr[0]);

// Function Call

maxSumSubseq(arr, N);

**return** 0;

}

Output:

50

Time Complexity:_ O(N * K)_

Auxiliary Space:_ O(N)_

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.

#arrays #dynamic programming #recursion #prefix-sum #prime number #sieve #subarray #subsequence

Brain  Crist

Brain Crist

1596646800

Maximum length of subarray consisting of same type of element

Given an array arr[] of N integers, the task is to find the maximum length of sub-array consisting of the same type of element on both halves of the sub-array. Also, the elements on both halves differ from each other.

Examples:

Input:_ arr[] = {2, 3, 4, 4, 5, 5, 6, 7, 8, 10}_

_Output: _4

Explanation:

_{2, 3}, {3, 4}, {4, 4, 5, 5}, {5, 6}, etc, are the valid sub-arrays where both halves have only one type of element. _

{4, 4, 5, 5} is the sub-array having maximum length.

_Hence, the output is 4. _

Input:_ arr[] = {1, 7, 7, 10, 10, 7, 7, 7, 8, 8, 8, 9}_

_Output: _6

Explanation:

_{1, 7}, {7, 7, 10, 10}, {7, 7, 7, 8, 8, 8}, {8, 9}, etc, are the valid sub-arrays where both halves have only one type of element. _

{7, 7, 7, 8, 8, 8} is the sub-array having maximum length.

_Hence, the output is 6. _

Naive Approach: The naive idea is to generate all possible subarray and check any subarray with maximum length can be divided into two halves such that all the elements in both the halves are the same.

Time Complexity:_ O(N3)_

Auxiliary Space:_ O(1)_

**Efficient Approach: **To solve this problem the idea is to use the concept of Prefix Sum. Follow the steps below to solve the problem:

  1. Traverse the array from the start in the forward direction and store the continuous occurrence of an integer for each index in an array forward[].
  2. Similarly, traverse the array from the end in the reverse direction and store the continuous occurrence of an integer for each index in an array backward[].
  3. Store the maximum of **_min(forward[i], backward[i+1])*2, _**for all the index where arr[i]!=arr[i+1].
  4. Print the value obtained in the above step.

Below is the implementation of the above approach:

  • C++
  • Python3

// C++ program for the above approach

#include <bits/stdc++.h>

**using** **namespace** std;

// Function that finds the maximum

// length of the sub-array that

// contains equal element on both

// halves of sub-array

**void** maxLengthSubArray(``**int** A[], **int** N)

{

// To store continuous occurence

// of the element

**int** forward[N], backward[N];

// To store continuous

// forward occurence

**for** (``**int** i = 0; i < N; i++) {

**if** (i == 0

|| A[i] != A[i - 1]) {

forward[i] = 1;

}

**else**

forward[i] = forward[i - 1] + 1;

}

// To store continuous

// backward occurence

**for** (``**int** i = N - 1; i >= 0; i--) {

**if** (i == N - 1

|| A[i] != A[i + 1]) {

backward[i] = 1;

}

**else**

backward[i] = backward[i + 1] + 1;

}

// To store the maximum length

**int** ans = 0;

// Find maximum length

**for** (``**int** i = 0; i < N - 1; i++) {

**if** (A[i] != A[i + 1])

ans = max(ans,

min(forward[i],

backward[i + 1])

* 2);

}

// Print the result

cout << ans;

}

// Driver Code

**int** main()

{

// Given array

**int** arr[] = { 1, 2, 3, 4, 4,

4, 6, 6, 6, 9 };

// Size of the array

**int** N = **sizeof**``(arr) / **sizeof**``(arr[0]);

// Function Call

maxLengthSubArray(arr, N);

**return** 0;

}

Output:

6

_Time Complexity: _O(N)

Auxiliary Space:_ O(N)_

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.

#arrays #greedy #mathematical #prefix-sum #subarray #subarray-sum

Brain  Crist

Brain Crist

1596661200

Print the Maximum Subarray Sum

Given an array arr[], the task is to find the elements of a contiguous subarray of numbers which has the largest sum.

Examples:

Input:_ arr = [-2, -3, 4, -1, -2, 1, 5, -3]_

Output:_ [4, -1, -2, 1, 5]_

_Explanation: _

In the above input the maximum contiguous subarray sum is 7 and the elements of the subarray are [4, -1, -2, 1, 5]

Input:_ arr = [-2, -5, 6, -2, -3, 1, 5, -6]_

Output:_ [6, -2, -3, 1, 5]_

_Explanation: _

In the above input the maximum contiguous subarray sum is 7 and the elements

of the subarray are [6, -2, -3, 1, 5]

Naive Approach: The naive approach is to generate all the possible subarray and print that subarray which has maximum sum.

Time complexity:_ O(N2)_

Auxiliary Space:_ O(1)_

Efficient Approach: The idea is to use the Kadane’s Algorithm to find the maximum subarray sum and store the starting and ending index of the subarray having maximum sum and print the subarray from starting index to ending index. Below are the steps:

  1. Initialize 3 variables endIndex to 0, currMax and globalMax to first value of the input array.
  2. For each element in the array starting from index(say i) 1, update currMax to max(nums[i], nums[i] + currMax) and globalMax and endIndex to i only if currMax > globalMax.
  3. To find the start index, iterate from endIndex in the left direction and keep decrementing the value of globalMax until it becomes 0. The point at which it becomes 0 is the start index.
  4. Now print the subarray between [start, end].

Below is the implementation of the above approach:

  • C++14

// C++ program for the above approach

#include <bits/stdc++.h>

**using** **namespace** std;

// Function to print the elements

// of Subarray with maximum sum

**void** SubarrayWithMaxSum(vector<``**int**``>& nums)

{

// Initialize currMax and globalMax

// with first value of nums

**int** endIndex, currMax = nums[0];

**int** globalMax = nums[0];

// Iterate for all the elemensts

// of the array

**for** (``**int** i = 1; i < nums.size(); ++i) {

// Update currMax

currMax = max(nums[i],

nums[i] + currMax);

// Check if currMax is greater

// than globalMax

**if** (currMax > globalMax) {

globalMax = currMax;

endIndex = i;

}

}

**int** startIndex = endIndex;

// Traverse in left direction to

// find start Index of subarray

**while** (startIndex >= 0) {

globalMax -= nums[startIndex];

**if** (globalMax == 0)

**break**``;

// Decrement the start index

startIndex--;

}

// Printing the elements of

// subarray with max sum

**for** (``**int** i = startIndex;

i <= endIndex; ++i) {

cout << nums[i] << " "``;

}

}

// Driver Code

**int** main()

{

// Given array arr[]

vector<``**int**``> arr

= { -2, -5, 6, -2,

-3, 1, 5, -6 };

// Function call

SubarrayWithMaxSum(arr);

**return** 0;

}

Output:

6 -2 -3 1 5

Time complexity:_ O(N)_

Auxiliary Space:_ O(1)_

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.

#arrays #dynamic programming #algorithms-dynamic programming #kadane #subarray #subarray-sum

Find array elements equal to sum of any subarray of at least size 2

Given an array arr[], the task is to find the elements from the array which are equal to the sum of any sub-array of size greater than 1.

Examples:

Input:_ arr[] = {1, 2, 3, 4, 5, 6}_

Output:_ 3, 5, 6_

Explanation:

The elements 3, 5, 6 are equal to sum of subarrays {1, 2},{2, 3} and {1, 2, 3} respectively.

Input:_ arr[] = {5, 6, 10, 1, 3, 4, 8, 16}_

Output:_ 4, 8, 16_

Explanation:

The elements 4, 8, 16 are equal to the sum of subarrays {1, 3}, {1, 3, 4}, {1, 3, 4, 8} respectively

Recommended: Please try your approach on {IDE} first, before moving on to the solution.

Approach: The idea is to use prefix sum array to solve the given problem. Create a prefix[] array that stores the prefix sum of all its preceding elements for every index. Store the sum of all subarrays in a map and search if any array element is present in the map or not.

#arrays #hash #prefix-sum #subarray #subarray-sum

Find array elements equal to sum of any subarray of at least size 2

Given an array arr[], the task is to find the elements from the array which are equal to the sum of any sub-array of size greater than 1.

Examples:

Input:_ arr[] = {1, 2, 3, 4, 5, 6}_

Output:_ 3, 5, 6_

Explanation:

The elements 3, 5, 6 are equal to sum of subarrays {1, 2},{2, 3} and {1, 2, 3} respectively.

Input:_ arr[] = {5, 6, 10, 1, 3, 4, 8, 16}_

Output:_ 4, 8, 16_

Explanation:

The elements 4, 8, 16 are equal to the sum of subarrays {1, 3}, {1, 3, 4}, {1, 3, 4, 8} respectively

Recommended: Please try your approach on {IDE} first, before moving on to the solution.

Approach: The idea is to use prefix sum array to solve the given problem. Create a prefix[] array that stores the prefix sum of all its preceding elements for every index. Store the sum of all subarrays in a map and search if any array element is present in the map or not.

#arrays #hash #prefix-sum #subarray #subarray-sum