携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第28天,点击查看活动详情
题目描述
给你一个下标从 0 开始的整数数组 nums ,你必须将数组划分为一个或多个 连续 子数组。
如果获得的这些子数组中每个都能满足下述条件 之一 ,则可以称其为数组的一种 有效 划分:
子数组 恰 由 2 个相等元素组成,例如,子数组 [2,2] 。 子数组 恰 由 3 个相等元素组成,例如,子数组 [4,4,4] 。 子数组 恰 由 3 个连续递增元素组成,并且相邻元素之间的差值为 1 。例如,子数组 [3,4,5] ,但是子数组 [1,3,5] 不符合要求。 如果数组 至少 存在一种有效划分,返回 true ,否则,返回 false 。
示例 1:
输入:nums = [4,4,4,5,6]
输出:true
解释:数组可以划分成子数组 [4,4] 和 [4,5,6] 。
这是一种有效划分,所以返回 true 。
示例 2:
输入:nums = [1,1,1,2]
输出:false
解释:该数组不存在有效划分。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/check-if-there-is-a-valid-partition-for-the-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路分析
- 今天的算法题目是数组形式的题目,题目要求将数组重新有效划分。题目定义子数组 恰 由 2 个相等元素组成,或者子数组 恰 由 3 个相等元素组成,或者子数组 恰 由 3 个连续递增元素组成,并且相邻元素之间的差值为 1。
- 理解清楚题意之后,如何去做呢? “如果数组 至少 存在一种有效划分,返回 true ,否则,返回 false 。” 从这一句可以得出,我们要使用三个条件,并且是或的关系,一真则真。
- 上面的三个有效划分,也可以理解为三个子问题。在这里,我们采用动态规划的方式解决问题。动态规划(Dynamic Programming, DP)是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。
- 我们定义 dp[i+1] 表示从 nums[0] 到 nums[i] 的这些元素能否有效划分。首先设置 dp[0] = true, 方便后面的逻辑判断。接着,依次写出上述三个条件的代码。根据逻辑判断,动态更新 dp[i + 1] 的情况。 具体实现代码如下,请参考。
通过代码
class Solution {
public boolean validPartition(int[] nums) {
int n = nums.length;
boolean[] dp = new boolean[n + 1];
dp[0] = true;
for (int i = 1; i < n; i++) {
boolean condition1 = (dp[i - 1] && nums[i] == nums[i - 1]);
boolean condition2 = i > 1 && dp[i - 2] && (nums[i] == nums[i - 1] && nums[i] == nums[i - 2]);
boolean condition3 = i > 1 && dp[i - 2] && (nums[i] == nums[i - 1] + 1 && nums[i] == nums[i - 2] + 2);
if (condition1 || condition2 || condition3) {
dp[i + 1] = true;
}
}
return dp[n];
}
}
总结
- 上述算法的是时间复杂度是O(n),空间复杂度是O(n)
- 在用DP思想解决问题的时候,需要注意子问题的拆分,这个题目已经帮助我们拆分好了子问题,理清逻辑关系,写出递推公式并验证。多写多练,更好的掌握DP解题方法。
- 坚持算法每日一题,加油!