携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第 18 天,点击查看活动详情
题目描述
给定一个整数数组 nums,你可以对数组进行若干次的划分把数组变为若干个子数组,如果经过划分后得到的子数组满足以下以下条件之一,则可以认为是有效划分,则结果返回true,否则返回false。
满足有效划分的子数组条件:
- 子数组由两个元素组成,且两个元素相等。
- 子数组由三个元素组成,且三个元素相等或者三个元素中下一个元素与上一个元素的差值恰为1。
例1:输入:nums=[2,2,3,4] 输出:false
解释:不存在有效划分的子数组,例如划分为nums1=[2,2]和nums2=[3,4],则nums2不符合有效划分,若划分为nums1=[2]和nums2=[2,3,4],则nums1不符合有效划分。
例2:输入:nums=[2,2,2,3,4] 输出:true
解释:可以划分为nums1=[2,2]和nums2=[2,3,4],可以看出存在有效划分
原题地址:2369. 检查数组是否存在有效划分
解题思路
本题为普通的线性动态规划问题,定义dp[i]用来表示前i个元素是否可以进行有效的划分。进行划分时,判断当前位置i的元素是否可以和前面的元素组成有效的子数组,可以分为三种情况:
- 若nums[i]==nums[i-1] ,则表示当前元素可以与上一个元素组成有效划分,此时如果dp[i-2]即前i-2个元素也能组成动态划分子数组,则前i个元素必能进行有效划分,此时dp[i]可置为true。
- 若nums[i]==nums[i-1]==nums[i-2] 或者 nums[i]-nums[i-1]==1且nums[i-1]-nums[i-2]==1 ,则表示当前元素可以与上一个元素以及上上个元素组成有效划分,此时如果dp[i-3]即前i-3个元素也能组成动态划分子数组,则前i个元素必能进行有效划分,此时dp[i]可置为true。
经过一步步的计算,最后返回的值即为dp[nums.size()-1],即nums是否可以进行有效划分。
实现代码
class Solution {
public:
bool validPartition(vector<int>& nums) {
// dp用来记录前i个元素是否可以进行有效划分
vector<bool> dp(nums.size(),false);
// 初始化前3个元素是否可以进行有效划分的信息
if(nums[0]==nums[1]) dp[1]=true;
if(nums.size()>2 && nums[0]==nums[1] && nums[0]==nums[2]) dp[2]=true;
if(nums.size()>2 && nums[1]-nums[0]==1 && nums[2]-nums[1]==1) dp[2]=true;
for(int i=3;i<nums.size();i++){
if(nums[i]==nums[i-1]) dp[i]=dp[i-2]|dp[i];
if(nums[i]==nums[i-1] && nums[i-2]==nums[i-1]) dp[i]=dp[i-3]|dp[i];
if(nums[i]-nums[i-1]==1 && nums[i-1]-nums[i-2]==1) dp[i]=dp[i-3]|dp[i];
}
return dp[nums.size()-1];
}
};