最长递增子序列LIS(Longest Increasing Sequence)

问题描述:

例:一个数组为[4, 5, 6 , 3]则最长的递增子序列为4 , 5,  6.


方法1

动态规划, dp[i]代表一nums[i]结尾的,递增子序列的最长长度

dp[i] = max(dp[i], dp[j]+1), j的取值范围是0到i - 1,所以时间复杂度是O(n^2)

int lengthOfLIS(vector<int>& nums) {
	if (nums.empty())
		return 0;
	vector<int> dp(nums.size(), 1);
	int ans = 1;
	for (int i = 1; i < nums.size(); ++i) {
		for (int j = i - 1; j >= 0; --j) {
			if (nums[i] > nums[j])
				dp[i] = max(dp[i], dp[j] + 1);
		}
		ans = max(ans, dp[i]);
	}
	return ans;
}

方法2:

定义一个数组tails, tails[i]代表的是长度为i+1的子序列的最小结尾。

例:[4, 5, 6 , 3],

len = 1   :      [4], [5], [6], [3]   => tails[0] = 3
len = 2   :      [4, 5], [5, 6]       => tails[1] = 5
len = 3   :      [4, 5, 6]            => tails[2] = 6

证明tails数组时递增的,假设tails[i - 1] > tails[i],那么就存在一个数以其结尾长度为i,但是小于tails[i - 1],与定义矛盾。

更新方法

1.如果nums[i]大于tails.back(),那么在tails后面加一个数。

2. tails[i-1] <= nums[i] <= tails[i],那么更新tails[i] = nums[i];

    int lengthOfLIS(vector<int>& nums) {
        vector<int> tails; //tails[i]代表长度为i+1的子序列的最小结尾
        for(int i = 0; i < nums.size(); ++i){
            auto iter = std::lower_bound(tails.begin(), tails.end(), nums[i]);
            if(iter == tails.end())
                tails.push_back(nums[i]);
            else
                *iter = nums[i];
        }
        return tails.size();
    }

ps:

//lower_bound返回指向第一个大于等于nums[i]的迭代器,没有则返回talis.end()
auto iter = lower_bound(tails.begin(), tails.end(), nums[i]);

//upper_bound返回第一个大于nums[i]的迭代器,没有则返回tails.end()
auto iter = upper_bound(tails.begin(), tails.end(), nums[i]);

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值