子数组问题

子数组的问题在面试中非常多,这里收集了一些子数组的问题,做一个总结:

1.连续子数组最大和
2.数组中最大连续递增子数组
3.数组中非连续最大递增子数组和
4.累加值为k的最长子数组,累加值不大于k的最长子数组


1. 连续子数组最大和

http://dsqiu.iteye.com/blog/1701494
连续子数组最大和,又叫最大子序列和或最大数组和,不过这里的序列好像有点不是很妥。

1.1问题描述

一个有N个元素的整型数组arr,有正有负,数组中连续一个或多个元素组成一个子数组,这个数组当然有很多子数组,求子数组之和的最大值。


2.

https://blog.csdn.net/dreamflyhua/article/details/21285247
这个题目有两种可能的

一种是求数组中最大的连续递增子序列,是连续递增的个数最大,而不是和。
方法一,通过辅助数组计数来完成:




第二种一种是求数组中连续递增子序列的最大和。

方法一:使用上面的双指针

这一种方法的思想其实和上面是一样的,去判断连续的递增数组的最大和,保存这个最大和,还是可以用双指针的办法,如果递增序列出现的断裂,这个时候记录断裂前的最大和,然后从断裂后重新开始计算。直到最后的指针到末尾了。

方法二:是否能采用dp的思想
dp[i] = dp[i-1]+a[i],while a[i]>a[i-1]>=0 && a[i]>a[i-1]<0;
dp[i] = a[i],while a[i]<a[i-1];


3.最长递增子序列(不连续)

http://dsqiu.iteye.com/blog/1701494

3.1问题描述

设L=<a1,a2,…,an>是n个不同的实数的序列,L的递增子序列是这样一个子序列Lin=<aK1,ak2,…,akm>,其中k1<k2<…<km且aK1<ak2<…<akm。求最大的m值。

3.2动态规划求解

从后向前分析,如果a[i]大于前面所有的数,则dp[i]在max{dp[j],j<i}的基础上加1(dp[i]表示数组a[i-1]为末尾的最长递增子序列的长度)。

设dp(i)表示L中以ai为末元素的最长递增子序列的长度。则有如下的递推方程: 这个递推方程的意思是,在求以ai为末元素的最长递增子序列时,找到所有序号在L前面且小于ai的元素aj,即j<i且aj<ai。如果这样的元素存在,那么对所有aj,都有一个以aj为末元素的最长递增子序列的长度dp(j),把其中最大的dp(j)选出来,那么f(i)就等于最大的f(j)加上1,即以ai为末元素的最长递增子序列,等于以使f(j)最大的那个aj为末元素的递增子序列最末再加上ai;如果这样的元素不存在,那么ai自身构成一个长度为1的以ai为末元素的递增子序列。

给出动态规划的方程:

dp[i] = max(dp[j])+1  while j<i,a[j]<a[i];
dp[i] = 1 else while

在这里插入图片描述

3.3 排序+LCS求解

这个方法也是很直观的,对原数组a进行排序得到一个有序的数组b, 这样出现在数组a的最长递增子序列也一定是数组b的子序列。那么问题就转到求两个序列的最长公共子序列了,LCS显然可以用二维的动态规划来实现。

这种方法非常的精辟,用一个数组来记录当前长度为l的数组的最小元素,那么遍历所有的序列,最后看数组的长度为多少,就是最长的序列长度,其中插入数组元素覆盖的时候可以使用二分法,这样的时间复杂度降到了nlgn;

https://www.felix021.com/blog/read.php?1587


4.

https://blog.csdn.net/qq_26916359/article/details/76150822

问题描述1:给定一个数组,值全部是正数,请返回累加值为给定值 k 的最长连续子数组的长度。


这种双指针的方法虽然可以,但是存在一个问题就是这些数字必须是正数,这样才能保证根据与k的大小调整滑动窗口的大小。

问题描述2:给定一个数组,值可以为正数负数和0,请返回累加和为给定值 K 的最长子数组长度。



这个问题就是利用映射表来完成滑动窗口的值,通过映射表记录所有的和的值,然后看窗口为k的结果。

问题描述3:给定一个数组,值可以为正数负数和0,请返回累加和不大于k的最长子数组长度。


在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值