最大子数组(I, II, III,IV,V)和最大子数组乘积 (动态规划)
I 找一个连续最大子数组,sum加到nums[i], 如果前面子数组和<0则舍去,从头开始。
class Solution {
public:
/**
* @param nums: A list of integers
* @return: A integer indicate the sum of max subarray
*/
int maxSubArray(vector<int> &nums) {
// write your code here
int ans=-0x3f3f3f3f,sum=;
for(int i=;i<nums.size();i++)
{
if(sum<)
{
sum=nums[i];
}
else sum+=nums[i];
ans=max(ans,sum);
}
return ans;
}
};
II 找两个不重叠的子数组,使得他们的和最大。
思路:一般有了I,II是变形版本,想办法往I上套,因为小规模的I已经做出来了,要好好利用他。
枚举划分的位置,将数组划分为左右两部分,每一部分调用I的函数就行了
class Solution {
public:
/*
* @param nums: A list of integers
* @return: An integer denotes the sum of max two non-overlapping subarrays
*/
int maxTwoSubArrays(vector<int> &nums) {
// write your code here
vector<int> left(nums.size(), -0x3f3f3f3f);
vector<int> right(nums.size(), -0x3f3f3f3f);
int sum=-0x3f3f3f3f,ans=-0x3f3f3f3f;
for(int i=;i<nums.size();i++)
{
if(sum<)
sum = nums[i];
else
sum+=nums[i];
ans=max(ans,sum);
left[i]=ans;
}
sum=-0x3f3f3f3f;
ans=-0x3f3f3f3f;
for(int i=nums.size()-;i>=;i--)
{
if(sum<)
sum = nums[i];
else
sum+=nums[i];
ans=max(ans,sum);
right[i]=ans;
}
ans=-0x3f3f3f3f;
for(int i=;i<nums.size();i++)
{
ans=max(ans,left[i-]+right[i]);
}
return ans;
}
};
III k个不重叠的子数组求其最大和
思路:
如何定义状态呢?一个状态必须包含题中所有信息,每一个状态都是独立不重复且覆盖每一种情况。
这样考虑,题干为一维数组,必须这样设计dp[i],从而遍历每一个位置。考虑到k个不重叠的子数组这一条件,那么这样设计dp[i][j]=所求答案(最大和), 不一定包含结点i,这一dp[nums.size()-1][k]就是答案。
如何设计状态转移方程呢?考虑前一状态怎么转移到现在的,由于是二维dp,我们这样考虑取一个中间状态dp[i][j],dp[i][j] = max( dp[i-1][j], )前一项是不加第i项,后一项要加第i项,
其中加第i项又分两种情况,第一种mustdp[i-1][j]+nums[i] 表示第i项并入第j个子数组, 第二种mustdp[i-1][j-1]+nums[i] 表示第i项独立成第j个子数组,为什么要新建一个数组mustdp,因为dp表示不一定包含最后一项,所以需要新建一个mustdp表示以最后一项结尾。综上所述:
mustdp[i][j] = max( dp[i-1][j-1] + nums[i],must[i-1][j] + nums[i] );
dp[i][j] = (dp[i-1][j], mustdp[i][j] );
一定要注意初始化条件,有负数不能初始化为0,且不能溢出。循环的时候要遍历过所有情况才行。下面程序中dp表示一定以最后一个元素结尾,udp表示不一定
class Solution {
public:
/**
* @param nums: A list of integers
* @param k: An integer denote to find k non-overlapping subarrays
* @return: An integer denote the sum of max k non-overlapping subarrays
*/
int maxSubArray(vector<int> &nums, int k) {
// write your code here for(int i=;i<nums.size();i++)
for(int j=;j<=k;j++)
{
udp[i][j]=-0x3f3f3f3f; // 注意防止溢出
dp[i][j]=-0x3f3f3f3f;
}
dp[][]=;
udp[][]=;
dp[][]=nums[];
udp[][]=nums[];
for(int i=;i<nums.size();i++)
{
dp[i][]=;
udp[i][]=;
for(int j=;j<=k;j++){ dp[i][j] = max(udp[i-][j-]+nums[i],dp[i-][j]+nums[i]);
udp[i][j] = max(udp[i-][j],dp[i][j]);
}
}
return udp[nums.size()-][k];
}
int dp[][];
int udp[][];
};
第一维表示到前一位的位置,这样写就涵盖了dp[0][1]的初始化形式更加规范。
思路:记mustTheLast[i][j]为在前i个数中分成j段,且第j段必须有第i个数的最大值,notTheLast[i][j]为前i个中分成j段,且第j段不一定含有第i个数的最大值;注意初始化的数据,不能全部初始化为0,不然在全部为负整数以及一些其他情况的数组会出错;
动态规划方程为:
mustTheLast[i][j] = max(mustTheLast[i-1][j] + nums[i-1] ,notTheLast[i-1][j-1] + nums[i-1]);
notTheLast[i][j] = max(notTheLast[i-1][j] ,mustTheLast[i][j]);
class Solution {
public:
/*
* @param nums: A list of integers
* @param k: An integer denote to find k non-overlapping subarrays
* @return: An integer denote the sum of max k non-overlapping subarrays
*/
int maxSubArray(vector<int> &nums, int k) {
// write your code here
int n = nums.size();
if(k > n)
return INT_MIN;
vector<vector<int> > notTheLast(n+,vector<int>(k+,-));
vector<vector<int> > mustTheLast(n+,vector<int>(k+,-));
mustTheLast[][] = ;
notTheLast[][] = ;
for(int i = ; i <= n; i++)
{
mustTheLast[i][] = ;
notTheLast[i][] = ; for(int j = ; j <= k; j++)
{
mustTheLast[i][j] = max(mustTheLast[i-][j] + nums[i-] ,notTheLast[i-][j-] + nums[i-]); notTheLast[i][j] = max(notTheLast[i-][j] ,mustTheLast[i][j]); } }
return notTheLast[n][k]; }
};
IV 找一个最大子数组,且其长度大于k
简单题,思路:前缀和,只是这次preMin是在第一个到第i-k个数内部找而已。还是最大化sum[j] - sum[i],就要求sum[i]一定要最小的,时间复杂度O(n)
V 找一个最大子数组,且其长度在区间[ k1, k2 ]
思路:看到区间类型的题,考虑维护一个最小(大)堆, 或类似形式的顺序队列,始终有序存储固定长度的候选值。
class Solution {
public:
/**
* @param nums an array of integers
* @param k1 an integer
* @param k2 an integer
* @return the largest sum
*/
int maxSubarray5(vector<int>& nums, int k1, int k2) {
// Write your code here
if (nums.size() < k1) {
return ;
} deque<int> dq;
vector<int> sum(nums.size()+, );
int maxSum = -0x3f3f3f3f;
for(int i=;i<=nums.size();i++)
{
sum[i] = sum[i-] + nums[i-];
while(!dp.empty() && dp.front()<i-k2)
dp.pop_front();
if(i>=k1)
{
while(!dp.empty() && sum[dp.back()]>sum[i-k1])
dp.pop_back();
dp.push_back(i-k1);
}
if(!dp.empty())
maxSum = max(maxSum, sum[i]-sum[dp.front()]);
}
return maxSum;
}
};
Maximum Product Subarray 求最大子数组乘积
因为包含正数、负数、0。乘积比求和更加复杂。
f[i]表示以i结尾的最大子数组乘积
g[i]表示以i结尾的最小子数组乘积
整体是f[i] = 乘以nums[i](乘的时候又分正最大负最小的情况) 或者 nums[i]
class Solution {
public:
int maxProduct(vector<int>& nums) {
int res = nums[], n = nums.size();
vector<int> f(n, ), g(n, );
f[] = nums[];
g[] = nums[];
for (int i = ; i < n; ++i) {
f[i] = max(max(f[i - ] * nums[i], g[i - ] * nums[i]), nums[i]);
g[i] = min(min(f[i - ] * nums[i], g[i - ] * nums[i]), nums[i]);
res = max(res, f[i]);
}
return res;
}
};
最大子数组(I, II, III,IV,V)和最大子数组乘积 (动态规划)的更多相关文章
- 买卖股票的最佳时机I II III IV
I 假设有一个数组,它的第i个元素是一支给定的股票在第i天的价格.如果你最多只允许完成一次交易(例如,一次买卖股票),设计一个算法来找出最大利润. II 假设有一个数组,它的第i个元素是一个给定的股票 ...
- LeetCode之“动态规划”:Best Time to Buy and Sell Stock I && II && III && IV
Best Time to Buy and Sell Stock I 题目链接 题目要求: Say you have an array for which the ith element is the ...
- Two Sum I & II & III & IV
Two Sum I Given an array of integers, find two numbers such that they add up to a specific target nu ...
- Best Time to Buy and Sell Stock I II III IV
一.Best Time to Buy and Sell Stock I Say you have an array for which the ith element is the price of ...
- combination sum(I, II, III, IV)
II 简单dfs vector<vector<int>> combinationSum2(vector<int>& candidates, int targ ...
- hdu 3081 hdu 3277 hdu 3416 Marriage Match II III IV //灵活运用最大流量
3081 意甲冠军: n女生选择不吵架,他甚至男孩边(他的朋友也算.并为您收集过程).2二分图,一些副作用,有几个追求完美搭配(每场比赛没有重复的每一个点的比赛) 后.每次增广一单位,(一次完美匹配) ...
- hdu 3081 hdu 3277 hdu 3416 Marriage Match II III IV //最大流的灵活运用
3081 题意: n个女孩选择没有与自己吵过架的男孩有连边(自己的朋友也算,并查集处理),2分图,有些边,求有几种完美匹配(每次匹配每个点都不重复匹配) 我是建二分图后,每次增广一单位,(一次完美匹配 ...
- Leetcode 137. Single Number I/II/III
Given an array of integers, every element appears twice except for one. Find that single one. 本题利用XO ...
- 数组中累加和为k的最大子数组的长度
package com.hzins.suanfa; import java.util.HashMap; public class demo { /** * 数组中累加和为k的最大子数组的长度 * @p ...
随机推荐
- Fusebox 类似WEBPACK 的工具,React Studio
Fusebox 类似WEBPACK 的工具, http://fuse-box.org/ React Studio: https://hackernoon.com/@reactstudio
- 华为QUIDWAY系列路由器的负载均衡配置
作者:邓聪聪 华为系列路由器的负载均衡NQA联动侦测配置案例: 需求:该局域网,IP地址(末位奇数)走联通,IP地址(末位偶数)走电信当某个运营商不可达时,自动切换.通过NQA来确定运营商是否可达., ...
- Net开发的部分知名网站案例
.Net开发的部分知名网站案例:http://www.godaddy.com 全球最大域名注册商http://www.ips.com 环迅支付,国内最早的在线支付平台http://www.icbc.c ...
- ranlib 作用
ar 命令用于更新,维护管理静态库. ranlib 命令用于 更新库的符号索引表. 当只执行了ar命令(用于更新)时, ld连接时会仍然报错,查找不到更新的变量或函数,此时需要用ranlib来更新库的 ...
- 优秀员工的修炼——通往专家、管理之路
(一)好员工的素质 好员工的类型有很多种,尝试着抽象出一个定义吧--好员工是那些主管分配其任务放心.同事喜欢与其共事.对自己工作负责.志在自我提升和价值实现的人.知识经济时代,好员工首先是做好自我管理 ...
- 【原创】Linux基础之命令行浏览器links
有时服务器环境受限,比如在内网环境不能暴露端口从外网访问,用curl看html代码比较累,这时可以使用命令行浏览器来查看相关页面 links 官方:http://links.twibright.com ...
- python字符串前面u,r,b的含义详解
u/U:表示unicode字符串 不是仅仅是针对中文, 可以针对任何的字符串,代表是对字符串进行unicode编码. 一般英文字符在使用各种编码下, 基本都可以正常解析, 所以一般不带u:但是中文, ...
- vmware 下找不到ifcfg-eth0的问题
找不大 eth0网卡,也就连不上网络,症状是ifconfig以后只现实lo,不显示eth0 ifconfig,显示的ip是ifcfg-lo的ip 解决办法 . 拷贝cp ifcfg-lo ifcfg- ...
- Confluence 6 数据库表-杂项(Miscellaneous)
这些部分是一些其他的表格,这些表格有必要在这里提及下能帮你更好的了解系统. os_propertyentry 有关实体和属性相关的特性. bandana 所有的持久层.这个表格包含的的内容有用户设置和 ...
- 学习Spring Boot:(一)入门
微服务 现在微服务越来越火了,Spring Boot热度蹭蹭直升,自学下. 微服务其实是服务化思路的一种最佳实践方向,遵循SOA(面向服务的架构)的思路,各个企业在服务化治理上面的道路已经走得很远了, ...