Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding subarrays in an array where length equals P * (sum of elements)

How would we go about testing all combinations of subarrays in a array where length of each subarray is equal to P times the sum of subarray elements.

A brief example: Edit:

 A = [2,-1,3,0,1,2,1] , P =2

Desired result:

  1. Length = 2,P * Sum of elements = 1 . Subarrays are [2,-1] , [0,1]

Edit Constraint :

N represents number of elements in an array
1 <= N <= 1e5
-1000 <= P <= 1000
|A[i]| <= 1e6

What kind of problem set(for eg:NP-hard?) does these kind of questions fall into ? Language : C#

like image 563
user1907849 Avatar asked Sep 23 '21 08:09

user1907849


People also ask

How do you calculate Subarrays?

For every index in the inner loop update sum = sum + array[j]If the sum is equal to the given sum then print the subarray. For every index in the inner loop update sum = sum + array[j] If the sum is equal to the given sum then print the subarray.

How do you find continuous sub array whose sum is equal to a given number in Java?

How do you find continuous sub array whose sum is equal to a given number in Java? Iterate through the array. At each element add the next n elements one by one, when the sum equals to the required value print the sub array.

How to get all the subarray of an array in Python?

1 Traverse the array from start to end. 2 From every index start another loop from i to the end of array to get all subarray starting from i, keep a varibale sum to calculate the sum. 3 For every index in inner loop update sum = sum + array [j] 4 If the sum is equal to the given sum then print the subarray.

How do you find the sum of a list of subarrays?

2. Hashing We can also use hashing to find subarrays with the given sum in an array by using a map of lists or a multimap for storing the end index of all subarrays having a given sum. The idea is to traverse the given array and maintain the sum of elements seen so far.

How to find contiguous subarray of integers in an array?

How to find contiguous subarray of integers in an array from n arrays such that the sum of elements of such contiguous subarrays is minimum 0 In an array, find an optimized algorithm for finding sum of lengths of longest subarray with current element being the highest in the subarray

How do you find the sum of an array in algorithm?

Algorithm: 1 Traverse the array from start to end. 2 From every index start another loop from i to the end of array to get all subarray starting from i, keep a varibale sum to calculate the sum. 3 For every index in inner loop update sum = sum + array [j] 4 If the sum is equal to the given sum then print the subarray.


Video Answer


2 Answers

This problem falls in P. Here's an O(n) solution.

Let's do some algebra with prefix sums:

j - i = p * (prefix_sum_j - prefix_sum_i)
j - i = p * prefix_sum_j - p * prefix_sum_i
j - p * prefix_sum_j = i - p * prefix_sum_i
p * prefix_sum_j - j = p * prefix_sum_i - i

JavaScript code with testing against brute force.

const f = (nums, p) =>
  nums.reduce(([map, sum, answer], val, i) => {    
    const newSum = sum + val;
    answer += p * newSum == i + 1;
    answer += map[p * newSum - i] || 0;
    map[p * newSum - i] = (map[p * newSum - i] || 0) + 1;
    return [map, newSum, answer];
  }, [{}, 0, 0])[2];


console.log('Input: [2,-1,3,0,1,2,1], 2')
console.log('Output: ' + f([2,-1,3,0,1,2,1], 2));


function bruteForce(A, p){
  let result = 0;

  for (let windowSize=1; windowSize<=A.length; windowSize++){
    for (let start=0; start<A.length-windowSize+1; start++){
      let sum = 0;

      for (let end=start; end<start+windowSize; end++)
        sum += A[end];
      
      if (p * sum == windowSize)
        result += 1;
    }
  }

  return result;
}


var numTests = 500;
var n = 20;
var m = 20;
var pRange = 10;

console.log('\nTesting against brute force...')

for (let i=0; i<numTests; i++){
  const A = new Array(n);
  for (let j=0; j<n; j++)
    A[j] = Math.floor(Math.random() * m) * [1, -1][Math.floor(Math.random()*2)];
  
  const p = Math.floor(Math.random() * pRange) * [1, -1][Math.floor(Math.random()*2)];

  _f = f(A, p);
  _brute = bruteForce(A, p);

  //console.log(String([_f, _brute, p, JSON.stringify(A)]));

  if (_f != _brute){
    console.log('MISMATCH!');
    console.log(p, JSON.stringify(A));
    console.log(_f, _brute);
    break;
  }
}

console.log('Done testing.')

In case it helps readers, the function, f, as a for loop could look like:

function f(A, p){
  const seen = {}; // Map data structure
  let sum = 0;
  let result = 0;
  
  for (let i=0; i<A.length; i++){
    sum += A[i];
    result += p * sum == i + 1; // Boolean evaluates to 1 or 0
    result += seen[p * sum - i] || 0;
    seen[p * sum - i] = (seen[p * sum - i] || 0) + 1;
  }
  
  return result;
}

My (first) attempt at C# code:

using System;
using System.Collections.Generic;

public class Solution{
  static int f(int[] A, int p){
    var seen = new Dictionary<int, int>();
    int sum = 0;
    int result = 0;
  
    for (int i=0; i<A.Length; i++){
      sum += A[i];
      result += Convert.ToInt32( p * sum == i + 1 );

      int key = p * sum - i;

      if (seen.ContainsKey(key)){
        result += seen[key];
        seen[key] += 1;

      } else {
        seen[key] = 1;
      }
    }
  
    return result;
  }


  public static void Main(){
    int[] A = new int[7]{2, -1, 3, 0, 1, 2, 1};
    int p = 2;

    Console.WriteLine(f(A, p));
  }
}
like image 125
גלעד ברקן Avatar answered Nov 05 '22 12:11

גלעד ברקן


I tried to solve this problem using dynamic programming. In my solution I have used 2 nested for loops for making the dp matrix so it should have time complexity of O(n^2) (not counting the 3 nested for loops used to print the solution). Since this problem can be solved using brute force method as well as using dynamic programming in polynomial time it has P complexity.

using System;

public class Program
{
    public static void Main()
    {
        int n = 7;
        int p = 2;
        int[, ] arr = new int[n + 1, n + 1];
        int[] nums = new int[]{2, -1, 3, 0, 1, 2, 1};
        for (int i = 1; i <= n; i++)
        {
            for (int j = i; j <= n; j++)
            {
                arr[i, j] = arr[i - 1, j - 1] + nums[j - 1];
            }
        }

        for (int j = 0; j <= n; j++)
        {
            for (int k = 0; k <= n; k++)
            {
                Console.Write(string.Format("{0} ", arr[j, k]));
            }

            Console.Write(Environment.NewLine);
        }

        Console.Write(Environment.NewLine + Environment.NewLine);
        for (int i = 1; i <= n; i++)
        {
            Console.WriteLine(string.Format("For length {0}:  ", i));
            for (int j = i; j <= n; j++)
            {
                if (p * arr[i, j] == i)
                {
                    Console.Write(string.Format("{0} {1}: ", (j - i + 1), j));
                    for (int k = j - i + 1; k <= j; k++)
                    {
                        Console.Write(string.Format("{0},", nums[k - 1]));
                    }

                    Console.Write(Environment.NewLine);
                }
            }

            Console.Write(Environment.NewLine);
        }

        Console.Write(Environment.NewLine);
    }
}

you can test this code on dotnetfiddle (this is the first c# code I have ever written so maybe some more optimizations could be done in code).

like image 38
Yashawant Avatar answered Nov 05 '22 11:11

Yashawant