• 代码题(25)— 最大子序和、最长上升子序列


    1、53. 最大子序和

    给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

    示例:

    输入: [-2,1,-3,4,-1,2,1,-5,4],
    输出: 6
    解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
    class Solution {
    public:
        int maxSubArray(vector<int>& nums) {
            if(nums.empty())
                return 0;
            int res = nums[0];
            int sum = nums[0];
            for(int i=1;i<nums.size();++i)
            {
                if(sum>0)
                    sum += nums[i];
                else
                    sum = nums[i];
                res = max(res, sum);    
            }
            return res;
        }
    };

    2、300. 最长上升子序列

    给定一个无序的整数数组,找到其中最长上升子序列的长度。

    示例:

    输入: [10,9,2,5,3,7,101,18]
    输出: 4 
    解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4

    说明:

    • 可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
    • 你算法的时间复杂度应该为 O(n2) 。

    进阶: 你能将算法的时间复杂度降低到 O(n log n) 吗?

      方法一:时间复杂度为O(n2)

      首先来看一种动态规划Dynamic Programming的解法,这种解法的时间复杂度为O(n2),类似brute force的解法,我们维护一个一维dp数组,其中dp[i]表示以nums[i]为结尾的最长递增子串的长度,对于每一个nums[i],我们从第一个数再搜索到i,如果发现某个数小于nums[i],我们更新dp[i],更新方法为dp[i] = max(dp[i], dp[j] + 1),即比较当前dp[i]的值和那个小于num[i]的数的dp值加1的大小,我们就这样不断的更新dp数组,到最后dp数组中最大的值就是我们要返回的LIS的长度.

    class Solution {
    public:
        int lengthOfLIS(vector<int>& nums) {
            if(nums.empty())
                return 0;
            int n = nums.size();
            int res=0;
            vector<int> dp(n,1);
            for(int i=0;i<n;++i)
            {
                for(int j=0;j<i;++j)
                {
                    if(nums[j]<nums[i])
                        dp[i]=max(dp[i],dp[j]+1);
                }
                res = max(res, dp[i]);
            }
            return res;
        }
    };

       方法二:时间复杂度为O(nlogn)

       思路是先建立一个空的dp数组,然后开始遍历原数组,对于每一个遍历到的数字,我们用二分查找法在dp数组找第一个不小于它的数字,如果这个数字不存在,那么直接在dp数组后面加上遍历到的数字,如果存在,则将这个数字更新为当前遍历到的数字,最后返回dp数字的长度即可,注意的是,跟上面的方法一样,特别注意的是dp数组的值可能不是一个真实的LIS。

    class Solution {
    public:
        int lengthOfLIS(vector<int>& nums) {
            if(nums.empty())
                return 0;
            vector<int> dp;
            for(int i=0;i<nums.size();++i)
            {
                int low=0,high=dp.size();
                while(low<high)
                {
                    int mid = (low+high)/2;
                    if(dp[mid]<nums[i])
                        low = mid+1;
                    else
                        high=mid;
                }
                if(high>=dp.size())
                    dp.push_back(nums[i]);
                else
                    dp[high] = nums[i];
            }
            return dp.size();
        }
    };
  • 相关阅读:
    Linux/Ubuntu tree 命令以树形结构显示文件夹目录结构
    apt-get install的默认安装路径
    error: (-215:Assertion failed) !_src.empty() in function 'cv::cvtColor'
    利用keras进行手写数字识别模型训练,并输出训练准确度
    OpenCV:图像的合并和切分
    OpenCV:图像的按位运算
    OpenCV:增加和减少图像的亮度,图像的加减法
    OpenCV:获取图像当中某一点的坐标
    OpenCV:图像的裁剪
    OpenCV:图像的水平、垂直、水平垂直翻转
  • 原文地址:https://www.cnblogs.com/eilearn/p/9376854.html
Copyright © 2020-2023  润新知