2369. Check if There is a Valid Partition For The Array
SourceWeekly Contest 305 Q3DifficultyMediumRating1779
Description
You are given a 0-indexed integer array nums. You have to partition the array into one or more contiguous subarrays.
We call a partition of the array valid if each of the obtained subarrays satisfies one of the following conditions:
- The subarray consists of exactly
2,equal elements. For example, the subarray[2,2]is good. - The subarray consists of exactly
3,equal elements. For example, the subarray[4,4,4]is good. - The subarray consists of exactly
3consecutive increasing elements, that is, the difference between adjacent elements is1. For example, the subarray[3,4,5]is good, but the subarray[1,3,5]is not.
Return true if the array has at least one valid partition. Otherwise, return false.
Example 1:
Input: nums = [4,4,4,5,6] Output: true Explanation: The array can be partitioned into the subarrays [4,4] and [4,5,6]. This partition is valid, so we return true.
Example 2:
Input: nums = [1,1,1,2] Output: false Explanation: There is no valid partition for this array.
Constraints:
2 <= nums.length <= 1051 <= nums[i] <= 106
Solutions
Solution 1: Memoization Search
Thinking
A partition uses two equals, three equals, or three consecutive increases. \(n \le 10^5\) makes naive recursion overlap. Validity from index \(i\) depends only on the suffix.
Memoize \(dfs(i)\): try a legal block of length \(2\) or \(3\) and jump to its end. Past \(n\) is success.
We design a function \(dfs(i)\), which represents whether there is a valid partition starting from index \(i\). So the answer is \(dfs(0)\).
The execution process of the function \(dfs(i)\) is as follows:
- If \(i \ge n\), return \(true\).
- If the elements at index \(i\) and \(i+1\) are equal, we can choose to make \(i\) and \(i+1\) a subarray, and recursively call \(dfs(i+2)\).
- If the elements at index \(i\), \(i+1\) and \(i+2\) are equal, we can choose to make \(i\), \(i+1\) and \(i+2\) a subarray, and recursively call \(dfs(i+3)\).
- If the elements at index \(i\), \(i+1\) and \(i+2\) increase by \(1\) in turn, we can choose to make \(i\), \(i+1\) and \(i+2\) a subarray, and recursively call \(dfs(i+3)\).
- If none of the above conditions are met, return \(false\), otherwise return \(true\).
That is:
To avoid repeated calculations, we use the method of memoization search.
The time complexity is \(O(n)\), and the space complexity is \(O(n)\). Where \(n\) is the length of the array.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
Solution 2: Dynamic Programming
Thinking
Solution 1 fills a suffix table from the end. The same three blocks can be written on prefixes: \(f[i]\) means the first \(i\) elements form a valid partition, taken from \(f[i-2]\) or \(f[i-3]\).
Fill left to right. The answer is \(f[n]\). Time stays \(O(n)\).
Solution 1 already decides each suffix from the end. Here we decide each prefix instead, using the same three blocks.
Let \(f[i]\) represent whether there is a valid partition for the first \(i\) elements of the array. Initially, \(f[0] = true\), and the answer is \(f[n]\).
The state transition equation is as follows:
The time complexity is \(O(n)\), and the space complexity is \(O(n)\). Where \(n\) is the length of the array.
1 2 3 4 5 6 7 8 9 10 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
1 2 3 4 5 6 7 8 9 10 11 12 | |
Solution 3: Dynamic Programming
Thinking
A partition is two equals, three equals, or three consecutive increases. \(n \le 10^5\), so trying blocks overlaps, and the pair is always tried first.
On an array of equal values that attempt is a chain of length \(n/2\), which overflows the stack.
Later indexes are known if we walk backward. Let \(f[i]\) mean the suffix from \(i\) has a valid partition, with \(f[n]\) true, and fill \(i\) from \(n-1\) down to \(0\). A legal block still jumps to \(i+2\) or \(i+3\).
Let \(f[i]\) mean there is a valid partition of the suffix starting at index \(i\). The answer is \(f[0]\), and \(f[n] = true\).
Fill \(i\) from \(n - 1\) down to \(0\). Two equal neighbors can continue from \(f[i + 2]\). Three equal values, or three values that increase by \(1\), can continue from \(f[i + 3]\). Take the or of those cases; if none applies, \(f[i]\) is false:
The time complexity is \(O(n)\), and the space complexity is \(O(n)\). Here, \(n\) is the length of the array.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
1 2 3 4 5 6 7 8 9 10 11 12 | |
1 2 3 4 5 6 7 8 9 10 11 12 | |