动态规划--牛牛的数列

在这里插入图片描述
这道题目遇到的问题:没有考虑到数可以增大,其实也可以减小~所以,必须从两个方向入手。从左边入手可以查看递增的,从右边入手查看递减的。下面第一种方法是 从左开始,只考虑让某个数增大形成递增数列; 从右边开始只考虑让某个数减少形成递减数列。== 因为只有两种情况,不是增大就是减小。

记录两种状态:使用两个列表,一个列表记录的是当前没有改变过数的最长数列; 一个记录的是改变了当前位置的数最长数列。

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;
    }
};
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值