Longest Increasing Subsequence 最长上升子序列

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

示例:

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

说明:

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

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

思路:

这道题参考了博文的思路

https://www.cnblogs.com/grandyang/p/4938187.html

时间复杂度O(nlogn),自己没想出来,而且感觉太复杂。具体思路如下:

维护一个递增数组dp,如果当前元素比dp的第一个元素小,就把第一个元素替换掉(覆盖第一个元素),如果比最后一个元素大,就插入到dp的最后(不覆盖最后一个元素),如果大小位于第一个元素和最后一个元素中,就通过二分法找到第一个大于该元素的位置,替换掉原始元素(覆盖)。

代码如下:

    int lengthOfLIS(vector<int>& nums) {
	vector<int> dp;
	if (nums.size() <= 0) {
		return 0;
	}
	dp.push_back(nums[0]);
	for (int i = 1; i < nums.size(); i++) {
		if (nums[i] < dp[0]) {
			dp[0] = nums[i];
			continue;
		}
		if (nums[i] > dp[dp.size() - 1]) {
			dp.push_back(nums[i]);
			continue;
		}
		int left = 0;
		int right = dp.size()-1;
		while (left < right) {
			int mid = left + (right - left) / 2;
			if (dp[mid] < nums[i]) {
				left = mid + 1;
			}
			else {
				right = mid;
			}
		}
		dp[right] = nums[i];
		     
    }
        return dp.size();  
    }

思路2:采用dp来做,通过维护一个一维数组dp来做,dp[i]表示到第i个元素的最长子序列的个数,那么dp[i+1]的值等于遍历[0,j]的元素(0<=j<=i),如果对应的nums[j]<nums[i]那么:

dp[i] = max(dp[j] + 1, dp[i]);

如果遍历完j都没有元素满足nums[j]<nums[i],那么把dp[i]赋值为1。

参考代码:

    int lengthOfLIS(vector<int>& nums) {
        if(nums.size()==0){
            return 0;
        }
	int *dp = new int[nums.size()];
	int res = 1;
	for (int i = 1; i < nums.size(); i++) {
		dp[i] = INT_MIN;
	}
	dp[0] = 1;
	for (int i = 1; i < nums.size(); i++) {
		for (int j = 0; j <= i; j++) {
			if (nums[j] < nums[i]) {
				dp[i] = max(dp[j] + 1, dp[i]);
				res = max(res, dp[i]);
			}
		}
        dp[i]=dp[i]==INT_MIN?1:dp[i];
	}

	delete[] dp;
	return res;        
    }




阅读更多
文章标签: leetcode
个人分类: 算法
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭