一、最大子数组和
. - 力扣(LeetCode)
二、环形子数组的最大和
. - 力扣(LeetCode)
class Solution {
public:int maxSubarraySumCircular(vector<int>& nums) {//动态规划思想解决 //环形数组问题,尝试转化成普通数组int n=nums.size();vector<int> f(n);f[0]=nums[0];auto g=f;for(int i=1;i<n;++i) {f[i]=max(nums[i],f[i-1]+nums[i]);//最大g[i]=min(nums[i],g[i-1]+nums[i]);//最小}int fmax=*max_element(f.begin(),f.end());int gmin=*min_element(g.begin(),g.end());int sum=accumulate(nums.begin(),nums.end(),0);return sum==gmin?fmax:max(fmax,sum-gmin);//有可能数据全是负数}
};
三、乘积的最大子数组
. - 力扣(LeetCode)
class Solution {
public:int maxProduct(vector<int>& nums) {//动态规划思想解决//负负得正可能更大//所以需要两个dp表示 一个是最大,一个是最小int n=nums.size();vector<int> f(n);f[0]=nums[0];auto g=f;for(int i=1;i<n;++i) {int x=nums[i];if(x>0) {f[i]=max(x,x*f[i-1]);g[i]=min(x,x*g[i-1]);}else{f[i]=max(x,x*g[i-1]);g[i]=min(x,x*f[i-1]);}}return *max_element(f.begin(),f.end());}
};
四、乘积为正数的最长子数组
. - 力扣(LeetCode)
class Solution {
public:int getMaxLen(vector<int>& nums) {//动态规划思想解决//负负得正可能更大//所以需要两个dp表示 一个是为正最长,一个是为负最小int n=nums.size();vector<int> f(n+1);//f[i]表示到i位置时乘积为正数的最长子数组长度auto g=f;//g[i]表示到i位置时乘积为负数的最长子数组长度for(int i=1;i<=n;++i){if(nums[i-1]>0){f[i]=f[i-1]+1;g[i]=g[i-1]==0?0:g[i-1]+1; //如果前面是0,那么这个数还是正数的话g[i]=0}else if(nums[i-1]<0){f[i]=g[i-1]==0?0:g[i-1]+1;//如果前面是0,那么这个数还是负数,f[i-1]就还是0g[i]=f[i-1]+1;}//else 本来就是0//f[i]=g[i]=0;}return *max_element(f.begin()+1,f.end());//第一个位置是不能算上的}
};
五、等差数组划分
. - 力扣(LeetCode)
class Solution {
public:int numberOfArithmeticSlices(vector<int>& nums){int n=nums.size();vector<int> dp(n);for(int i=2;i<n;++i)if(nums[i]+nums[i-2]==nums[i-1]*2) dp[i]=dp[i-1]+1;return accumulate(dp.begin(),dp.end(),0);}
};
六、最长湍流子数组
. - 力扣(LeetCode)
七、单词拆分
. - 力扣(LeetCode)
class Solution {
public:bool wordBreak(string s, vector<string>& wordDict) {// 优化⼀:将字典⾥⾯的单词存在哈希表⾥⾯unordered_set<string> hash;for(auto& s : wordDict) hash.insert(s);int n=s.size();vector<bool> dp(n+1);dp[0]=true;//确保后面填表是正确的s=' '+s;//在字符串前加一个空格,确保dp表和s的下标映射是一样的//在动规涉及到子串问题常用的技巧for(int i=1;i<=n;++i)//开始填表{for(int j=i;j>=1;--j) //找到第一个满足要求的位置{if(dp[j-1]==true&&hash.count((s.substr(j,i-j+1)))) {dp[i]=true;break;}}}return dp[n];}
};
八、环绕字符串中的唯一子字符串
. - 力扣(LeetCode)
class Solution {
public:int findSubstringInWraproundString(string s) {//dp[i]表示以i位置结尾有多少子串在base中出现int n=s.size();vector<int> dp(n,1);for(int i=1;i<n;++i)//开始填表if((s[i]-s[i-1]+26)%26==1) //说明符合要求dp[i]=dp[i-1]+1;//但是得去重 (y z a b c 和 a b c)// 2. 计算每⼀个字符结尾的最⻓连续⼦数组的⻓度 //相同字符的dp值,我们取最大的vector<int> hash(26);for(int i=0;i <n; ++i) hash[s[i] - 'a'] = max(hash[s[i]-'a'], dp[i]);// 3. 将所有结果累加起来return accumulate(hash.begin(), hash.end(), 0);}
};