前言

2017年的六月份到九月份,陆陆续续在leetcode上面刷了130道题目。

眼瞅着明年开年就要开始求职找实习。于是重新开始了一波刷题。
现在的选择是使用lintcode,相比leetcode,我认为lintcode更好的是:
1.有中文版的,用起来比较熟悉。
2.记笔记比较方便。
3.题目比leetcode少一些,题不在多,在于精。
4.可以创建群组,一起刷题,看到群里刷题动态(包括代码和笔记)。
5.有倒计时功能。(一般简单15min,中等30min,困难45min),这个比较能模拟真实面试场景。
正题
这次参与刷题的一共有四人(嘟嘟、琼琼、东东、博主)。
41.最大子数组
dp[i] = max(dp[i-1],0)+a[i] (空间可用O(1))
PS:百度面试题
42.最大子数组2
找两个不重叠的子数组,让和最大。
双向DP。(前向后向分别找最大)
43.最大子数组3
给一个k,找出k个不重叠的子数组,让和最大。
local[i][m]表示到第i个位置,分为m个子数组的局部最大和(最后一个子数组包含第i个元素)
global[i][m]表示到第i个位置,分为m个子数组的全局最大和(最后一个子数组不一定包含第i个元素)
要这样去分,是因为状态转移的时候需要用到。比如第i+1个位置的元素能不能拼到最后一个子数组里,还是另开一个子数组。
状态转移方程为:
local[i][m] = max(global[i-1][m-1],local[i-1][m])+nums[i] (需要包含第i个元素,max里面第一项表示新开一个子数组,第二项表示把第i个元素拼到最后一个子数组上)
global[i][m] = max(local[i][m],global[i-1][m])(从当前局部最大和之前的全局最大中找)
AC代码:
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//到第i个位置在内,分为m个不重叠的子数组//要看包含第i-1个位置(分为m个),到第i-1个位置、不一定包含第i-1个位置(分为m-1个)int len = nums.size();vector<vector<int> > local(len,vector<int>(k)); //一定包含第i位置vector<vector<int> > global(len,vector<int>(k)); //不一定包含第i个位置for(int i=0;i<len;++i){for(int m=0;m<k;++m){if(m>i) break;if(m==0){local[i][m] = i==0?nums[i]:max(local[i-1][m],0)+nums[i];global[i][m] = i==0?nums[i]:max(local[i][m],global[i-1][m]);}else{local[i][m] = i-1>=m?max(global[i-1][m-1],local[i-1][m])+nums[i]:global[i-1][m-1]+nums[i];global[i][m] = i-1>=m?max(local[i][m],global[i-1][m]):local[i][m];}}}return global[len-1][k-1];}
};

44.最小子数组
和41最大子数组类似

45.最大子数组差
和42最大子数组2类似。
双向DP。(前向最大 后向最小)和(前向最小 后向最大)
138.子数组之和
找到和为0的子数组,返回起始位置和结束位置。
用sum[i]记录到0位置到i位置的和,O(n^2)方法会超时。【python的O(n^2)可以过,面试估计就GG了。。】
类似2 sum的题目,使用map,把之前的和都存到map中。
存在的话,说明已经找到了。
初始化map[0]=-1;
AC代码:
class Solution {
public:/** @param nums: A list of integers* @return: A list of integers includes the index of the first number and the index of the last number*/vector<int> subarraySum(vector<int> &nums) {// write your code hereint len=nums.size(), sum=0;vector<int> res(2);map<int,int> mp;mp[0]=-1;for(int i=0;i<len;++i){sum+=nums[i];if(mp.find(sum)!=mp.end()){res[0]=mp[sum]+1,res[1]=i;return res;}mp[sum]=i;}}
};
139.最接近零的子数组和
sum[i]表示0到i位置的和,那么求sum[j]-sum[i]就可以求得子数组和,然后再选择最小的。这样时间是O(n^2),我们只需要找最接近0的,那么我们何不将这些sum数组排序,然后挨着的两个找呢。
191.乘积最大子序列
比较笨拙的办法是我之前使用的:
由于要求最大乘积,而且都是整数。那么我们只用考虑负数的个数即可,如果是偶数,全部连乘即可。如果是奇数个,那么只用考虑最左边的负数(左右两边分别单独连乘)和最右边的负数(左右两边分别单独连乘)。然后需要用0来做边界。
后来和同学讨论,发现这题其实很简单。。。
由于是连乘最大。我们只用保留之前的最大和最小即可。(最小的乘以负数变为最大)
两种方法都可以过,但是第二种写起来会简单许多:乘积最大子序列
402.连续子数组求和
类似41,只是需要返回边界。可以使用双指针,或者先得到右边界再算左边界
617.最大平均子数组(好题!!)
长度大于等于K的子数组平均值最大。
拿到这题首先是没有思路,想到的方法只能是O(n^2),但是提示我会超时,n的个数达到10^4。
我们的目标是求这个平均值,那这个值的范围在哪里呢?
令数组中最小元素为min,最大值为max。那么平均值的范围必须是[min,max]。
我们设平均值为x,如果有一个O(n)的方法能判断长度大于等于K的子数组平均值大于x或者小于等于x,这样时间复杂度就变成了O(n*log2(max-min))。因为我们将left=min,right=max,mid=(left+right)/2,如果最大平均值大于mid,直接让left=mid;如果最大平均值小于等于mid,让right=mid。
我们使用sum[i]表示0位置到i位置的元素之和。由于之前是平均值不确定,数组的长度不确定,i到j的平均值为(sum[j]-sum[i])/(j-i)。这样的计算必须是O(n^2)。
而现在我们只需要判断最大平均值是不是大于mid。我们将每个元素都减去mid,我们现在只需要判断最大平均值是不是大于0。而(sum[j]-sum[i])/(j-i)是不是大于0,直接等价为sum[j]-sum[i]是不是大于0。
而算sum[j]-sum[i]里的最大值不需要枚举每个i和j。我们在遍历数组的时候只需要记录和位置j 距离为k以上的最小值即可。而这个最小值是可以很轻易的得到的。
AC代码:
class Solution {
public:/** @param nums: an array with positive and negative numbers* @param k: an integer* @return: the maximum average*/double maxAverage(vector<int> &nums, int k) {int len = nums.size();double l=nums[0],r=nums[0],mid,eps=1e-6;vector<double> sum(len+1);for(int i=1;i<len;++i){l = min(l,double(nums[i]));r = max(r,double(nums[i]));}while(r-l>eps){mid = (r+l)/2;double pre=0;bool flag=false;sum[0]=0;for(int i=1;i<=len;++i)sum[i]=sum[i-1]+nums[i-1]-mid;for(int i=k;i<=len;++i){if(sum[i]-pre>eps){flag=true;break;}pre = min(pre,sum[i-k+1]);}if(flag) l=mid;else r=mid;}return r;}
};
番外
想到了最近今日头条实习生面试的一道题目。
题意是让求一个子数组,让子数组里的最小元素乘以子数组的和最大。(最小数字*区间和 最大)
这个题目的来源是POJ 2796
当然O(n^2)的方法面试官当然是不满意的。
现在最主要的问题是确定每个数字的边界,在左边找一个比它小的第一个元素位置,在右边找一个比它小的第一个元素的边界。然后计算每个数字乘以对应的区间和即可。
如何找每个数字的边界,一般的做法是维护一个单调递增栈。遍历数组,如果比栈顶大,就入栈,如果比栈顶小,说明边界找到了。(如果比栈顶小,那么栈顶元素的左边界是次顶元素的位置,右边界是当前元素的位置)
AC代码:(nums[i]用cin的话会超时,scanf有输入优化)
#include<iostream>
#include<stack>
#include<cstdio>
#define maxn 100005
using namespace  std;long long nums[maxn];
long long sum[maxn]; //记录和int main(){int n,i;int l,r; //结果的左边界,右边界。long long ans,tmp; //最后的结果while(cin>>n){ans = l = r =  0;stack<int> stac; //单调递增栈for(i=0;i<n;++i){scanf("%lld",&nums[i]);sum[i]=i==0?nums[i]:sum[i-1]+nums[i];}nums[n]=0;for(i=0;i<=n;++i){while(!stac.empty()&&nums[stac.top()]>nums[i]){long long cur = nums[stac.top()];stac.pop();if(stac.empty()) tmp = sum[i-1]*cur;else tmp = (sum[i-1]-sum[stac.top()])*cur;if(tmp>ans) ans=tmp,r=i-1,l=stac.empty()?0:stac.top()+1;}stac.push(i);}cout<<ans<<endl;cout<<l+1<<" "<<r+1<<endl;}return 0;
}

同样的类型还有leetcode 84

给一个数组,让求数组构成的图里面的最大矩形。
问题来了,在左边找一个比它小的第一个元素位置,在右边找一个比它小的第一个元素的边界。然后计算每个数字乘以对应的区间长度即可。
是不是和上面的题目特别相似啊。。。
AC代码:
class Solution {
public:int largestRectangleArea(vector<int>& heights) {int len = heights.size(),res=0;heights.push_back(0);stack<int> stac;for(int i=0;i<=len;++i){while(!stac.empty()&&heights[stac.top()]>heights[i]){int tmp = heights[stac.top()];stac.pop();tmp = stac.empty()?tmp*i:tmp*(i-1-stac.top());res = max(res,tmp);}stac.push(i);}return res;}
};

lintcode 子数组问题(最全的面试子数组问题)相关推荐

  1. 要闻君说:阿里云联合8家芯片模组商推出“全平台通信模组”;北汽与小桔车服联合“京桔”;IBM要帮助印度公司打造5G战略!...

    关注并标星星CSDN云计算 每周三次,打卡即read 更快.更全了解泛云圈精彩news go go go  嗨,大家好!偶是要闻君.盼望着.盼望着,放假的日子又临近了一步,抢先祝福各位看官们新年快乐哈 ...

  2. lintcode 矩阵问题(最全的面试矩阵问题)

    前言 第三周我们计划刷关于矩阵的题目. 此次参与刷题的共五人(嘟嘟.琼琼.东东.大智.博主). 首次把宿舍的白板用上了.. 正题 28.搜索二维矩阵 每行都是有序的,且下一行第一个元素比上一行最后一个 ...

  3. 阿里云联合8家芯片商推“全平台通信模组”,加速物联网生态建设...

    因为此次合作,其中部分合作伙伴已经收获了一个月新客户同比线下增长500%的惊人成果. 1月28日晚间消息,阿里云宣布联合业内8家芯片模组商推出"全平台通信模组",帮助用户通过该模组 ...

  4. redis cluster 集群 HA 原理和实操(史上最全、面试必备)

    文章很长,建议收藏起来慢慢读!疯狂创客圈总目录 语雀版 | 总目录 码云版| 总目录 博客园版 为您奉上珍贵的学习资源 : 免费赠送 经典图书:<Java高并发核心编程(卷1)> 面试必备 ...

  5. element ui 图片控件 排序_JAVA全栈面试前端基础之四 Vue+Element框架快速开发

    本文主要包括以下4个内容 什么是ElementUI Vue 中引入ElementUI Vue+elementUI构建后台管理系统 开源项目推荐 1.什么是ElementUI 官网:https://el ...

  6. 最全Java面试180题:阿里11面试+网易+百度+美团!含答案大赠送!

    网络编程 ISO模型与协议 http1.0:需要使用keep-alive参数来告知服务器端要建立一个长连接 http1.1:默认长连接.支持只发送header信息,可以用作权限请求.支持Host域. ...

  7. 史上最全Redis面试49题(含答案):哨兵+复制+事务+集群+持久化等

    最全面试题答案系列 史上最强多线程面试44题和答案:线程锁+线程池+线程同步等 最全MySQL面试60题和答案 史上最全memcached面试26题和答案 史上最全Spring面试71题与答案 今天主 ...

  8. 阿里最全Java面试100题汇总:涵盖天猫、蚂蚁金服等面试题!含答案~

    [阿里天猫.蚂蚁.钉钉面试题目] 1.微信红包怎么实现. 2.海量数据分析. 3.测试职位问的线程安全和非线程安全. 4.HTTP2.0.thrift. 5.面试电话沟通可能先让自我介绍. 6.分布式 ...

  9. BAT面试进阶:最全Memcached面试30题含答案

    [memcached面试题目] Memcached服务在企业集群架构中应用场景? Memcached服务在不同企业业务应用场景中的工作流程? Memcached服务分布式集群如何实现? Memcach ...

最新文章

  1. 独家 | 这15个最热门的GitHub库你不可错过!
  2. java cutdown_Java并发程序入门介绍
  3. 产品分析报告|读书新贵——《网易蜗牛读书》
  4. LeetCode 94. 二叉树的中序遍历(中序遍历)
  5. 实验四——多分支结构及本章总结
  6. PyTorch中的model.modules(), model.children(), model.named_children(), model.parameters(), model.nam...
  7. 《自动驾驶网络解决方案白皮书》研读(一):电信产业自动驾驶网络探索与实践
  8. [Swift]LeetCode20. 有效的括号 | Valid Parentheses
  9. godaddy虚拟主机access数据库中文乱码的解决方法
  10. 《JavaScript高级程序设计(第3版)》.Nicholas.C.Zakas.扫描版.pdf
  11. css 背景渐变详解
  12. [OfficeExcel] OfficeExcel2010 第23讲 Excel饼图美化与PPT图表
  13. 数据分析|爬取14455个基金,千万别被人当成韭菜给割了
  14. linux驱动-设备驱动模型
  15. 利用群体遗传数据估计基因组上重组率
  16. IP地址计算---子网掩码确定和子网划分等详解 (附常见相关习题)
  17. 全文检索引擎ElasticSearch:文档管理、集成IK分词器
  18. pdf java解析_用java如何解析pdf文件
  19. 计算机课程教材审读意,用好部编本小学语文教材值得注意的11个问题
  20. mysql中常用的三种插入数据的语句

热门文章

  1. MS12 020补丁下载for sever 2003_x86_chs
  2. MaxDOS 8.0 发布,全面支持WIN7及X64系统
  3. 高级 Java 面试必问的三大 IO 模型,你 get 了吗?
  4. 2021年安全员-B证(陕西省)考试及安全员-B证(陕西省)找解析
  5. 243 mysql获取某个表中除了某个字段名外的所有字段名
  6. 小度音箱+esp8266做语音控制开关
  7. python音频处理相关库
  8. docker 删除所有未启动的容器_Docker数据卷容器及DockerFile
  9. 从C4D建模到Three.js实现闹钟产品360度展示效果(.stl,.obj,.mtl)
  10. 7-11如何塑造出令人发指的用户体验