Wednesday, January 20, 2021

Number of Arithmetic progression slices of at least length of 3

Problem: An arithmetic progression is sequence of numbers if the difference between the numbers are same. For example:

1, 3, 5, 7, 9, 11

Given an array say 'arr', return the number of subarrays whose length is at least 3 and the numbers in the each subarray form an arithmetic progression. 

Example:

arr = [1, 3, 5, 7, 11, 15]

return: 4, arithmetic progression slices in arr: [1, 3, 5], [3, 5, 7], [1, 3, 5, 7] and [7, 11, 15].


Approach: We can use the similar approach which we have taken in maximum sum subarray, basically there whenever we see that the current sum is negative, we reset the sum to 0 and start another subarray. Here we can maintain current length of the arithmetic progression and whenever we see that the arithmetic progression has been broken, we reset the the current length to 2 and look further.

Whenever we find the difference between arr[i] - arr[i - 1] is not equal to current diff then we can see if the current length is greater than or equal to 3. If that is the case we need to add the number of arithmetic progressions of length >= 3 formed by the current subarray to the final result. 

If you dry run multiple examples, you will find the number of arithmetic progressions of length >= 3 given the current length is:

1+ 2 + 3 + ... + (current_length - 3 + 1)

= 1 + 2 + 3 + ... + (current_length - 2)

= ((current_length - 2) * (current_length - 2 + 1)) / 2

= ((current_length - 2) * (current_length - 1)) / 2


Implementation in C#:

        public static int NumberOfArithmeticSlices(int[] arr)

        {

            if (arr?.Length < 3)

            {

                return 0;

            }

            int numArthSlices = 0;

            int currLength = 2;

            int currDiff = arr[1] - arr[0];

            for (int i = 2; i < arr.Length; ++i)

            {

                if (currDiff == arr[i] - arr[i - 1])

                {

                    ++currLength;

                }

                else

                {

                    if (currLength >= 3)

                    {

                        numArthSlices += GetNumSlices(currLength);

                    }

                    currDiff = arr[i] - arr[i - 1];

                    currLength = 2;

                }

            }

            // for the last arithmetic progression subarray

            return currLength < 3 ? numArthSlices : numArthSlices + GetNumSlices(currLength);

        }


        private static int GetNumSlices(int currLength)

        {

            return ((currLength - 2) * (currLength - 1)) / 2;

        }


Complexity: O(n)

No comments:

Post a Comment