3

Given an integer array nums, find number of distinct contiguous subarrays with at most k odd elements. Two subarrays are distinct when they have at least one different element.

I was able to do it in O(n^2). But need solution for O(nlogn).

Example 1:

Input: nums = [3, 2, 3, 4], k = 1
Output: 7 
Explanation: [3], [2], [4], [3, 2], [2, 3], [3, 4], [2, 3, 4]
Note we did not count [3, 2, 3] since it has more than k odd elements.

Example 2:

Input: nums = [1, 3, 9, 5], k = 2
Output: 7
Explanation: [1], [3], [9], [5], [1, 3], [3, 9], [9, 5]

Example 3:

Input: nums = [3, 2, 3, 2], k = 1
Output: 5
Explanation: [3], [2], [3, 2], [2, 3], [2, 3, 2]
[3], [2], [3, 2] - duplicates
[3, 2, 3], [3, 2, 3, 2] - more than k odd elements

Example 4:

Input: nums = [2, 2, 5, 6, 9, 2, 11, 9, 2, 11, 12], k = 1
Output: 18
Prachi Palod
  • 31
  • 1
  • 2

3 Answers3

2

We can solve this in sub quadratic complexity by a two step process. First use two pointers to outline the relevant windows, which we will use to build a generalised suffix tree. We can prove that all the windows together are O(n) length by noting that each overlap will be inserted only twice. The first window is constructed by extending from the first element as far right as we can keep a valid subarray. Subsequent windows are created by (1) extending the left pointer just after the next odd element, and (2) extending the right pointer as far as we can keep a valid subarray.

Example 1:

3, 2, 3, 2
k = 1

windows: [3 2], [2 3 2]


Example 2:

1, 2, 2, 2, 3, 4, 4, 5, 5
k = 2

windows:
[1 2 2 2 3 4 4], [2 2 2 3 4 4 5], [4 4 5 5] 

Build a generalised suffix tree. The count of distinct subsets will equal the sum of cumulative lengths of the suffixes stored in the tree. (By "cumulative length" I mean: for example, given suffix "abc", we would add 1 + 2 + 3, each time extending farther from the start of the suffix. Or by formula n * (n + 1) / 2)

As kcsquared noted in the comments, there's no need for a generalised suffix tree. Rather we can use a known way to "count total distinct substrings with a suffix array and the longest common prefix array, but instead of summing over n - suffix_array_elements, ...replace the n with the maximal right boundary for that index."

גלעד ברקן
  • 23,602
  • 3
  • 25
  • 61
  • Can you explain what you mean by 'outline the relevant windows' and 'all the windows together are O(n)'? Which windows are you referring to? It also seems unnecessary to build a generalised suffix tree instead of a regular one, although perhaps I'm misunderstanding this based on the earlier comment about windows. The total length of all maximal valid subarrays starting at each position can be quadratic, so you must be dealing with the overlap in some other way. – kcsquared Sep 11 '21 at 14:17
  • Can you please tell what is complexity of building of suffix tree for k=n? – Vladimir Nesterovsky Sep 11 '21 at 14:18
  • @VladimirNesterovsky if k == n, there would be only one window. – גלעד ברקן Sep 11 '21 at 14:20
  • @kcsquared I gave an example of the windows (the elements are space-separated, and the windows are comma-separated) in the answer. The tree deals with the overlap but I'll be happy to hear how to do it with a suffix array on just the input. – גלעד ברקן Sep 11 '21 at 14:32
  • @גלעדברקן I'm not sure I understand how the windows are defined in the first place. To do this with just a suffix array ([Idea taken from this C++ implementation](https://leetcode.com/discuss/interview-question/278341/Uber-or-Phone-Screen-or-Distinct-subarrays-with-at-most-k-odd-elements/797178)) is exactly the same way you count total distinct substrings with a suffix array and the longest common prefix array, but instead of summing over n - suffix_array_elements, you replace the n with the maximal right boundary for that index. This is probably clearer in the linked code. – kcsquared Sep 11 '21 at 14:42
  • @kcsquared I added a description and examples of the window construction. I also updated the answer to include the more efficient concept you described. – גלעד ברקן Sep 11 '21 at 15:02
0

Consider an array consisting purely of odd elements.

Number of result subarrays is n*k. If k is, say, equal to n then number of subarrays is ~n*n.

So, you want to find ~n*n subarrays using O(nlogn) operations.

I doubt there is an algorithm with requested complexity.

  • It is highly surprising that an O(n log n) algorithm for this problem exists; yet it is also true, and there are several implementations using suffix arrays. Using Farach's algorithm for Suffix Trees, there is an O(n) solution if the elements of nums are at most polynomial in magnitude. In fact, since we don't need the exact suffix tree for this problem, there's likely an unconditional O(n) solution as well. Putting the exact text of the question title into Google shows a Leetcode post with n log n C++ code. – kcsquared Sep 11 '21 at 14:06
  • This does not prove that an algorithm with complexity lower than O(n^2) does not exist. – TYeung Sep 12 '21 at 04:40
  • I did not tell I have a proof but expressed doubts. I accept my knowledge gaps, and have already studied that suffix tree may be built as n*logn or even as linear complexity task. This tree can be queried with linear complexity to find requested answer. – Vladimir Nesterovsky Sep 12 '21 at 19:29
0

If we just need to output number of subarrays then I believe it can be done using two pointer approach + sliding window in O(n) time complexity.

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-ask). – Community Sep 12 '21 at 00:32