Divide and Conquer_1.最大连续子数组
给定一个数组,求它的一个子数组,使其求和最大。
这个问题的应用:给定一只股票很多天的价格,计算从哪天买进哪天卖出能获得最大利润。
给定
prices:100 113 98 87 65 78 120 110 115
计算delta
delta: 13 -15 -11 -22 13 42 -10 5
求delta数组的最大连续子数组就能得到最大利润。
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1231
解法1:Devide and Conquer
1)将delta按中点分为两个数组left[l...mid]、right[mid+1...r],最大子数组要么在left中,要么在right中,要么跨越left和right。
2)将其递归划分至原子问题,left中一个元素,right中一个元素。最大子数组要么是left[l],要么是right[r],要么是left[l]+right[r]。
3)先不考虑跨越left和right的情况,那么求left和right中的最大子数组,就是原问题的子问题,原问题时间复杂度T(n),该子问题复杂度为T(n/2)。
4)将求跨越left和right的最大子数组的问题额外处理。其最大值一定是 left中以mid为右端点的最大子数组 加上 right中以mid+1为左端点的最大子数组。求这个问题的时间复杂度可以做到O(n)。最终T(n)=2T(n/2)+O(n),整个问题的复杂度为O(nlogn)。
#include<iostream>
#include<cstdio>
using namespace std; #define N 10005 struct Pair {
int sum, left,right;
Pair() {}
explicit Pair(int s, int l, int r)
{
sum = s;
left = l;
right = r;
}
bool operator < (const Pair& p)const
{
return sum < p.sum;
}
bool operator <= (const Pair& p)const
{
return sum <= p.sum;
}
}; int n, num[N],preSum[N],sufSum[N]; Pair findMaxCrossSubarr(int l, int r)
{
int mid = (l + r) / ,lmax_l=mid,rmax_r=mid+,lmax=num[mid],rmax=num[mid+];
for (int i = l; i < mid; i++)
{
int tmp = preSum[mid] - preSum[i - ];
if (tmp > lmax)
{
lmax = tmp;
lmax_l = i;
}
}
for (int i = mid + ; i <= r; i++)
{
int tmp = sufSum[mid + ] - sufSum[i+];
if (tmp > rmax)
{
rmax = tmp;
rmax_r = i;
}
}
//cout << rmax + lmax << " " << lmax_l << " " << rmax_r << endl;
/*if(rmax+lmax<0)
return Pair(0, l, r);
else */
return Pair(rmax + lmax, lmax_l, rmax_r); } Pair findMaxSubarr(int l, int r)
{
if (l == r)
return Pair(num[l], l, r);
int mid = (l + r) / ;
Pair lpair = findMaxSubarr(l, mid);
Pair rpair = findMaxSubarr(mid + , r);
Pair xpair = findMaxCrossSubarr(l, r);
//cout << "*" << lpair.sum << " " << rpair.sum << " " << xpair.sum << endl;
if (rpair <= lpair&&xpair <= lpair)
return lpair;
else if (lpair < rpair&&xpair < rpair)
return rpair;
else
return xpair;
} int main()
{
while (scanf_s("%d", &n) != EOF && n)
{
for (int i = ; i <= n; i++)
{
scanf_s("%d", &num[i]);
preSum[i] = preSum[i - ] + num[i];
}
for (int i = n; i > ; i--)
sufSum[i] = sufSum[i + ] + num[i];
Pair res = findMaxSubarr(, n);
//printf("%d %d %d\n", res.sum, res.left, res.right);
if (res.sum < )
printf("0 %d %d\n", num[], num[n]);
else
printf("%d %d %d\n", res.sum, num[res.left], num[res.right]);
//cout << endl;
}
return ;
}
解法2:Dynamic Programming 线性时间复杂度
假如知道以r为右端点的最大子数组,将其扩展到以r+1为右端点的最大子数组,若dp[r]>=0,则dp[r+1]=dp[r]+num[r+1];若dp[r]<0,则dp[r+1]=num[r+1];
#include<iostream>
#include<cstdio>
using namespace std; #define N 10005 int main()
{
int n;
while (scanf_s("%d", &n) != EOF && n)
{
int num[N];
for (int i = ; i <= n; i++)
scanf_s("%d", &num[i]);
int dp = -, dp1 = , l = , r = , maxn = -, tl = , tr = ;
for (int i = ; i <= n; i++)
{
if (dp < )
{
dp = num[i];
tl = tr = i;
}
else
{
dp += num[i];
tr = i;
}
if (dp > maxn)
{
maxn = dp;
l = tl;
r = tr;
}
}
if(maxn<)
printf("0 %d %d\n", num[], num[n]);
else
printf("%d %d %d\n", maxn, num[l], num[r]);
}
return ;
}
Divide and Conquer_1.最大连续子数组的更多相关文章
- LeetCode 581. Shortest Unsorted Continuous Subarray (最短无序连续子数组)
Given an integer array, you need to find one continuous subarray that if you only sort this subarray ...
- [LeetCode] Shortest Unsorted Continuous Subarray 最短无序连续子数组
Given an integer array, you need to find one continuous subarray that if you only sort this subarray ...
- Java课程课后作业190315之从文档中读取随机数并得到最大连续子数组
从我上一篇随笔中,我们可以得到最大连续子数组. 按照要求,我们需要从TXT文档中读取随机数,那在此之前,我们需要在程序中写入随机数 import java.io.File; import java.i ...
- Leetcode 581.最短无序连续子数组
最短无序连续子数组 给定一个整数数组,你需要寻找一个连续的子数组,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序. 你找到的子数组应是最短的,请输出它的长度. 示例 1: 输入: [2, ...
- LeetCode 581. 最短无序连续子数组(Shortest Unsorted Continuous Subarray)
581. 最短无序连续子数组 581. Shortest Unsorted Continuous Subarray 题目描述 给定一个整型数组,你需要寻找一个连续的子数组,如果对这个子数组进行升序排序 ...
- 【LeetCode】1438. 绝对差不超过限制的最长连续子数组 Longest Continuous Subarray With Absolute Diff Less Than or Equal t
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 滑动窗口 日期 题目地址:https://leetco ...
- The Day Two 找到一个具有最大和的连续子数组,返回其最大和
""" 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1,2,1,-5, ...
- Leetcode581.Shortest Unsorted Continuous Subarray最短无序连续子数组
给定一个整数数组,你需要寻找一个连续的子数组,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序. 你找到的子数组应是最短的,请输出它的长度. 示例 1: 输入: [2, 6, 4, 8, 1 ...
- 力扣1438. 绝对差不超过限制的最长连续子数组-C语言实现-中等难度
题目 传送门 文本 给你一个整数数组 nums ,和一个表示限制的整数 limit,请你返回最长连续子数组的长度,该子数组中的任意两个元素之间的绝对差必须小于或者等于 limit . 如果不存在满足条 ...
随机推荐
- CRM 配置 ADFS后,使用自定义STS遇到的问题总结
1 登录ADFS服务查看 ADFS日志 2 根据日志提示的错误,设置ADFS对应的属性 (Get-ADFSRelyingPartyTrust) | Set-ADFSRelyingPartyTrust ...
- Linux下高并发socket最大连接数所受的各种限制(详解)
1.修改用户进程可打开文件数限制 在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统为每 ...
- windows系统下mysql5.5查看和设置数据库编码
1.显示当前编码命令: show variables like 'char%'; 2.设置编码为utf8命令:set names 'utf8';
- codeforces 688E E. The Values You Can Make(dp)
题目链接: E. The Values You Can Make time limit per test 2 seconds memory limit per test 256 megabytes i ...
- bzoj1566 [NOI2009]管道取珠——DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1566 一眼看上去很懵... 但是答案可以转化成有两个人在同时取珠子,他们取出来一样的方案数: ...
- Ubuntu下搭建基于apache2的gerrit+gitweb服务器
说明:Ubuntu版本12.04 1. 配置gerrit管理帐号 1 sudo adduser gerrit 增加sudo权限: 1 sudo usermod -a -G sudo gerrit 切换 ...
- mysql 联合2个列的数据 然后呈现出来
SELECT a.voyageNum,CONCAT(a.startDate,'~',a.endDate) AS 日期 FROM tchw_voyageoilcost a ,tchw_voyageoi ...
- Tomcat相关的LNMT和LAMT
Tomcat相关的LNMT和LAMT LNMT:Linux Nginx MySQL Tomcat Client (http) --> nginx (reverse proxy)(http) -- ...
- E20180228-hm-xa
bounds n. 界限; 界限; 出界; 在(某人允许进入的)界限以外; 出格的; 跳跃( bound的名词复数 ); (球等的) 反跳; indice n. 指数(指指标, 如健康指数的指数); ...
- J201700525-hm
スケルトン 骨組み(ほねぐみ) 骨架 リソース 资源