Count Subarrays with Consecutive elements differing by 1 - arrays

I am going through this program mentioned here.
Given an array arr[] of N integers. The task is to count the total number of subarrays of the given array such that the difference between the consecutive elements in the subarrays is one. That is, for any index i in the subarrays, arr[i+1] – arr[i] = 1.
Examples:
Input : arr[] = {1, 2, 3}
Output : 3
The subarrays are {1, 2}. {2, 3} and {1, 2, 3}
Input : arr[] = {1, 2, 3, 5, 6, 7}
Output : 6
Efficient Approach: An efficient approach is to observe that in an array of length say K, the total number of subarrays of size greater than 1 = (K)*(K-1)/2.
So, the idea is to traverse the array by using two pointers to calculate subarrays with consecutive elements in a window of maximum length and then calculate all subarrays in that window using the above formula.
Below is the step-by-step algorithm:
Take two pointers to say fast and slow, for maintaining a window of consecutive elements.
Start traversing the array.
If elements differ by 1 increment only the fast pointer.
Else, calculate the length of the current window between the indexes fast and slow.
My question is about the statement An efficient approach is to observe that in an array of length say K, the total number of subarrays of size greater than 1 = (K)*(K-1)/2 How this formula (K)*(K-1)/2 is derived?

The number of subarrays of size 1 is K.
The number of subarrays of size 2 is K-1.
( We need to select subarrays of size 2, hence we can have pair with the indices (0,1), (1,2), .......(K-1,K). In total we can have K-1 such pairs)
The number of subarrays of size 3 is K-2.
...
...
The number of subarrays of size K is 1
So, the number of subarrays of size greater than 1 is
= K-1 + K-2 + K-3+ ...... 1
= (K + K-1 + K-2 + K-3+ ...... 1) - K //adding and removing K
= (K(K+1)/2) - K
= K(K-1)/2

Related

Maximum Sum Elements in Range

Given an array 'A' of size 'N' containing integers. You need to answer
'Q' queries of type [ L R X Y ]. In each of the query you need to
select at least 'X' elements and at most 'Y' elements from range 'L'
to 'R' of the array 'A' such that their sum is maximum.
Output the maximum sum achievable for each of the query.
Example :
N = 5
A = [ 1, 2, -1, -2, 3 ]
Q = [ [ 1, 3, 1, 2 ] , [ 3, 4, 1, 2 ] ]
Output : 3, -1
Expanation :
For query 1, we select integers 1 and 2 to get the sum 3. This is the
maximum sum achievable in the range index 1 to 3.
For query 2, we need to select at least 1 element so we select -1 to
get maximum sum -1.
Note :
The selected elements in the range L to R need not be consecutive. You can > select subsequence of integers to maximise the sum.
Constraints :
1<=N<=10^5
1<=Q<=10^5
-10^8 <= A[i] <= 10^8
1<=L<=R<=N
1<=X<=Y<=R-L+1
I tried to think of some approaches but could not find any algo for the above constraints. Any help/hint would be appreciated.
One approach is to preprocess the numbers by splitting into non-overlapping arrays of length L (for L equal to different powers of 2).
Sort each array, and compute the cumulative sum of each array.
Then for each query, identify the arrays which combine to make the query range and use bisection to identify the level T such that if taking all elements above T we end up with a legal number of elements and the highest sum.
There will be log(N) arrays involved, and log(N) steps in each bisection, so this should be reasonably fast.
(Note if our first evaluation shows that taking all positive elements ends up with too many, we need to find the lowest legal level by bisection, while if we end up with too few we need to find the highest legal level by bisection)
Example
Suppose we have an array A = [ 1, -1, 2, -2, 3, -3, 4, 0 ].
The preprocessing will split it into:
Two arrays of length 4: [ 1, -1, 2, -2], [ 3, -3, 4, 0 ]
Four arrays of length 2: [ 1, -1], [2, -2], [ 3, -3], [4, 0 ]
Eight arrays of length 1: [1], [-1], [2], [-2], [ 3], [-3], [4], [0 ]
Then with a query 3 to 5, we want the elements [-2,3,-3] which we can form from the arrays [-2] and [3,-3].
Suppose we now want to find the maximum sum from at least 2 elements.
We first try taking all positive elements, this only results in 1 element so we know we need to bisect for the highest legal level.
The bisection could work by trying some values, e.g.
All elements >= 0 gives 1 element, so value is too high
All elements >= -4 gives 3 elements, so value is too low
All elements >= -2 gives 2 elements, so value is just right

Divide array into equal sized subarrays

we are given an array of size n (n is even), we have to divide it into two equal-sized subarrays array1 and array2, sized n/2 each such that product of all the numbers of array1 equals to the product of all the numbers in array2.
Given array:
arr = [2, 4, 5, 12, 15, 18]
solution:
array2 = [4, 5, 18]
array1 = [2, 12, 15]
Explanation:
product of all elements in array1 is 360
product of all elements in array2 is 360.
This problem might be soved using dynamic programming. You need to get subset of size n/2 with product equal to p = sqrt(overall_product). Note that there is no solution when overall_product is not exact square.
Recursion might look like
solution(p, n/2, arr) = choose valid solution from
solution(p / arr[i], n/2-1, arr without arr[i])
return true for arguments (1,0,...)
use memoization or table to solve problem with merely large n values.

Determining the maximum sum of elements among M groups with N elements

You are given an integer array a of size n and an integer m. you have to distribute the elements of array A into M groups such that the maximum sum of elements in each group is minimum and the elements of array A allocated to any group is contiguous. Write a program to determine the maximum sum of elements among all the groups.
The brute force could be having all the M possible sub-arrays from the given array and checking with them. But this would take a time complexity of O(n^3).
Here I used dynamic programming which would take both the time and space complexity of O(n*M).
Try all the possible partitions that are possible using recursion. Let dp[ind][k] be the minimum of maximum sums till index 'ind' with 'k' partitions. Hence the possible states will be partition at every index from the index ind till n. The minimum of maximum sums of all those states will be our answer.
In order not to recur for visited element, we can use memoize.
Below is the implementation of the above approach:
from sys import maxsize
from sys import setrecursionlimit
setrecursionlimit(10**6)
def max_sum_groups_min(arr, n, ind, M, dp):
# If M segments have been divided
if M == -1:
# If we are at the end
if ind == n:
return -maxsize
# If we do not reach end, return a maximum number
# that cannot be a min value than existing answer
return maxsize
# If at the end, but M segmments are not formed
if ind == n:
return maxsize
# If it's already visited: Memoization
if dp[ind][M] != False:
return dp[ind][M]
ans = maxsize
cur = 0
# Iterate and try to break at every segment and create a segment
for i in range(ind, n):
# sum of elements in current segment
cur += arr[i]
# Find the maximum of all segments after adding and
# find minimum in all possible combinations
ans = min(ans, max(max_sum_groups_min(arr, n, i + 1, M - 1, dp), cur))
# Return the answer by memoizing it
dp[ind][M] = ans
return ans
n = int(input("Enter array size: "))
arr = list(map(int, input("Enter list of elements: ").split()))
group = int(input("Enter the group size: "))
# keeping 'False' inorder to keep track it's not visited
dp = [[False for _ in range(group)] for _ in range(n)]
print(max_sum_groups_min(arr, n, 0, group - 1, dp))
For eg: n = 8, arr = [1, 2, 3, 4, 5, 6, 7, 8], M = 4
Here the given array can be divided into 4 groups as:
{1, 2, 3, 4}, {5, 6}, {7}, {8}
in which 2nd group has largest sum(11) among all the groups which is minimum of all possibilities.
Thanks,
Jayanth.

Longest subsequence with elements greater than its length

Given an array of n elements, find the longest subsequence of k (k<=n) elements which contain only elements greater than or equal to k.
For example:
Array: [3, 1, 5, 1, 6]
Output: 3 (the subsequence 3, 5, 6 meets the requirements
because 3,5,6 are all greater than 3.)
How can I do this in O(n)?
I tried my best, but all I can come up with is O(n logn).

Filling fixed sized array with either integer 1 or 2 to make a sum X

Let's say I have a fixed sized array. I want to fill the array with either 1s or 2s so that all element sums up to X.
Example:
Required sum = 12
Array size = 7
Possible combinations:
array( 1, 2, 2, 2, 1, 2, 2 ) // sums to 12
array( 1, 1, 2, 2, 2, 2, 2 ) // sums to 12
Find the number of 2's in the array, this number is:
#2's = X - array_size
Chose random arbitrary #2's elements (for example the first elements), and
give them the value 2, the rest of the elements will get the value 1.
Note: it is easy to see that if X < array_size or X> 2*array_size there is no solution to the problem (and obviously the above algorithm will fail)

Resources