这道题目遇到的问题:没有考虑到数可以增大,其实也可以减小~所以,必须从两个方向入手。从左边入手可以查看递增的,从右边入手查看递减的。下面第一种方法是 从左开始,只考虑让某个数增大形成递增数列; 从右边开始只考虑让某个数减少形成递减数列。== 因为只有两种情况,不是增大就是减小。
记录两种状态:使用两个列表,一个列表记录的是当前没有改变过数的最长数列; 一个记录的是改变了当前位置的数最长数列。
class Solution:
def maxSubArrayLength(self , nums ):
# write code here
n = len(nums)
dp = []
if not nums:
return 0
dp1 = [0]*n
dp2 = [0]*n
dp1[0] = 1
dp2[0] = 1
pre = nums[0]
for i in range(1, n):
if nums[i] > nums[i-1]:
dp1[i] = dp1[i-1] + 1
if i-2 >= 0 and nums[i] > nums[i-2]:
dp2[i] = max(dp1[i-1], dp2[i-1]) + 1
else:
dp2[i] = dp1[i]
else:
dp1[i] = 1
dp2[i] = dp1[i-1] + 1
dp3 = dp1
dp4 = dp2
## 增加下面的情况是因为还可以减小。
dp1 = [0]*n
dp2 = [0]*n
dp1[-1] = 1
dp2[-1] = 1
for i in range(n-2, 0, -1):
if nums[i] < nums[i+1]:
dp1[i] = dp1[i+1] + 1
if i+2 < n and nums[i] < nums[i+2]:
dp2[i] = max(dp1[i+1], dp2[i+1]) + 1
else:
dp2[i] = dp1[i]
else:
dp1[i] = 1
dp2[i] = dp1[i+1] + 1
return max(max(dp1), max(dp2), max(dp3), max(dp4))
下面的做法比上面更加优秀,首先记录两个数组,分别是从左往右依次递增的数目\从右往左; 然后是判断改变当前数能否使得两个数列叠加更大,改变的前提是nums[i+1] > nums[i-1],因为默认整数,所以就是nums[i+1] - nums[i-1] > 0, 中间就可以容纳一个数了。
class Solution {
public:
int maxSubArrayLength(vector<int>& nums) {
int n=nums.size();
if(n<3)return n;
int left[n],right[n];
for(int i=0;i<n;i++){
left[i]=1;
right[i]=1;
}
for(int i=1;i<n;i++){
if(nums[i]>nums[i-1])
left[i]=left[i-1]+1;
}
for(int i=n-1;i>0;i--){
if(nums[i-1]<nums[i])
right[i-1]=right[i]+1;
}
int ans=1;
for(int i=1;i<n-1;i++){
if(nums[i+1]-nums[i-1]>0){
ans=max(ans,(left[i-1]+right[i+1])+1);
} // 这里其实就是考虑到两边一起~~~为什么考虑两边一起呢
//因为可以增大也可以减少呀
// 比如 1 2 3 4 100 6 7 8 9
}
return ans;
}
};