Russian Doll Envelopes-最长递增子序列

18 篇文章 0 订阅
15 篇文章 0 订阅

方法:DP+ 二分搜索

具体一点说,二分搜索是用在LIS(最长递增子序列)中(LIS见:点击打开链接)。主要思想就是LIS的思想。

有O(N*N)和O(NlgN)两种解法。

不论是哪种解法,首先都得按照w(宽)值对envelopes进行递增排序。

简单直观的O(N*N)的方法。

class Solution {
public:
	int maxEnvelopes(vector<pair<int, int>>& envelopes) {
		int size = envelopes.size();
		quicksort(envelopes, 0, size - 1);
		int maxN = judge(envelopes);
		return maxN;
	}
	int quicksort(vector<pair<int, int>>& envelopes, int s, int e){
		if (s >= e)return 0;
		int  Ref = envelopes[e].first;
		int i = s - 1, j = s;
		pair<int, int> temp;
		for (; j<e; ++j){
			if (envelopes[j].first<Ref){
				i++;
				temp = envelopes[j];
				envelopes[j] = envelopes[i];
				envelopes[i] = temp;
			}
		}
		temp = envelopes[j];
		envelopes[j] = envelopes[i + 1];
		envelopes[i + 1] = temp;
		quicksort(envelopes, s, i);
		quicksort(envelopes, i + 2, e);
		return 1;
	}
	int judge(vector<pair<int, int>>& envelopes) {
		int size = envelopes.size(), largest,result=1;
		if (size == 0) return 0;
		vector<int> count;
		count.push_back(1);
		for (int i = 1; i < size; ++i){
			largest = 0;
			for (int j = 0; j < i; ++j){
				if (envelopes[i].first>envelopes[j].first&&envelopes[i].second>envelopes[j].second&&count[j]>largest)
					largest = count[j];
			}
			count.push_back(largest + 1);
			if (largest + 1 > result) result = largest + 1;
		}
		return result;
	}
};
在上面排序的基础上,对w相同的envelopes再按照h进行递减排序(当时就递减排序没想到)。(递减为了让w相同信封不嵌套)

然后应用二分搜索。(对stl不熟悉,自己写的排序,二分搜索等,代码很长,但时间还是在很行beat70%)

class Solution {
public:
	int maxEnvelopes(vector<pair<int, int>>& envelopes) {
		int size = envelopes.size();
		vector<int> w, h;
		for (int i = 0; i < size; ++i)
			w.push_back(envelopes[i].first);
		quicksort(envelopes, w, 0, size - 1, -1);//-1表示从小到大排序,1表示从大到小排序,
		for (int i = 0; i < size; ++i)
			h.push_back(envelopes[i].second);
		w.push_back(-1);
		int s = 0;
		for (int i = 1; i <= size; ++i)
		{
			if (w[i] != w[i - 1]){
				quicksort(envelopes, h, s, i-1, 1); //具有相同w的,按h由大到小排序
				s = i;
			}
		}
		int maxN = LIS(h);
		return maxN;
	}
	int quicksort(vector<pair<int, int>>& envelopes, vector<int>& vect, int s, int e, int order){
		if (s >= e)return 0;
		int  Ref = vect[e];
		int i = s - 1, j = s;
		int temp;
		pair<int, int> temp1;
		for (; j<e; ++j){
			if ((vect[j] - Ref)*order>0){
				i++;
				temp = vect[j];
				vect[j] = vect[i];
				vect[i] = temp;
				temp1 = envelopes[j];
				envelopes[j] = envelopes[i];
				envelopes[i] = temp1;
			}
		}
		temp = vect[j];
		vect[j] = vect[i + 1];
		vect[i + 1] = temp;
		temp1 = envelopes[j];
		envelopes[j] = envelopes[i + 1];
		envelopes[i + 1] = temp1;
		quicksort(envelopes, vect, s, i, order);
		quicksort(envelopes, vect, i + 2, e, order);
		return 1;
	}
	int LIS(vector<int>& h) {
		int size = h.size();
		if (size == 0) return 0;
		vector<int> temp;
		temp.push_back(h[0]);
		int len = 1, pos;                                 //用于标示temp数组中的元素个数
		for (int i = 1; i<size; i++)
		{
			if (h[i]>temp[len - 1]) //如果大于temp中最大的元素,则直接插入到temp数组末尾
			{
				temp.push_back(h[i]);
				len++;
			}
			else
			{
				pos = BiSearch(temp, h[i]);//二分查找需要插入的位置
				temp[pos] = h[i];
			}
		}
		return len;
	}
	int BiSearch(vector<int>& temp, int key){
		int len = temp.size();
		int low = 0, high = len - 1, mid;
		while (low <= high)
		{
			mid = (low + high) / 2;
			if (temp[mid]>key)
				high = mid - 1;
			else if (temp[mid]<key)
				low = mid + 1;
			else
				return mid;
		}
		return low; //数组data中不存在该元素,则返回该元素应该插入的位置
	}
};
看讨论里面用stl函数,代码很短,值得好好学习。如下:

class Solution {
public:
    int maxEnvelopes(vector<pair<int, int>>& envelopes) 
    {
        int size = envelopes.size();
        sort(envelopes.begin(), envelopes.end(), [](pair<int, int> a, pair<int, int>b){
            return a.first<b.first || (a.first==b.first && a.second>b.second);
        });
        vector<int> collector;
        for(auto& pair: envelopes)
        {
            auto iter = lower_bound(collector.begin(), collector.end(), pair.second);
            if(iter == collector.end()) collector.push_back(pair.second);
            else if(*iter > pair.second) *iter = pair.second;
        }
        return collector.size();
    }
};
下面这句搞定了上面提到的两次不同的排序:

        sort(envelopes.begin(), envelopes.end(), [](pair<int, int> a, pair<int, int>b){
            return a.first<b.first || (a.first==b.first && a.second>b.second);
        });
下面搞定了二分搜索等:

        for(auto& pair: envelopes)
        {
            auto iter = lower_bound(collector.begin(), collector.end(), pair.second);
            if(iter == collector.end()) collector.push_back(pair.second);
            else if(*iter > pair.second) *iter = pair.second;
        }
但是时间都差不多,比我的稍慢。





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值