[LeetCode]problem 354. Russian Doll Envelopes
2016-06-19 10:53
190 查看
TAG
二维元素的最长递增序列题目链接
方法
不知怎么,直觉使然,觉得应该使用排序+LIS。然而仅仅是直觉却不能解决问题,有两个问题需要解决:
排序策略
LIS策略
自己之前想的是排序先按w递增,再按h递增;LIS存储数组使用vector的vector,因为每个状态可能有多个值:
如下面的情况: [2,3] , [5,8], [6,4] , [6,7] , [7,8]
到处理[6,4]时,LIS数组是 [2,3], [5,8]
此时[6,4]虽然w比[5,8]大,但是h小,我们不能替换[5,8] (假设后面有[6,10],替换后就错误了),又不能抛弃(抛弃后最优解就被抛弃了)。所以就只能存储起来。这样复杂度就成了O(n^2).
不是很好的方法,或者说,想得不清楚。
看了DISCUSS Java NLogN Solution with Explanation, 找到了问题的答案。 巧妙!
排序策略是,按w递增,w想等时h递减排序
LIS只求h的LIS
上面的逻辑全面地解决了该问题。为什么?首先,我们要找的序列,是一个w递增,h也递增的最长序列。我们按w递增排序保证了w都是递增的。
关键是w相等时h递减排序。DISCUSS也说了原因,因为对于 [6,4] , [6,7]这样的元素,如果按h递增,显然只求h的LIS就错了!因为虽然h递增了,但是w是相等的,套不进去。而当我们逆序时,其实解决的问题是: 在w相同时,我们避免了上述不正确地扩张LIS数组。因为最大的已经放前面的,后面的就不可能去在w相同的情况下,扩展长度。这样一来,w相同的不会扩张,w递增的h则不受影响,所以完美地解决了问题——此时,我们只需看h,找到最长的h递增序列就好了。
再尝试解释一遍:这种情况下,找到的序列,h必然是递增的没有问题(因为是LIS),而且w必然也是递增的(因为首先已经按w递增排序,其次相同的w对应的h是递减的,所以不会有相同w对应的pair出现在结果中)。
太厉害!
代码
class Solution { public: int maxEnvelopes(vector<pair<int, int>>& envelopes) { size_t nrEnvelopes = envelopes.size() ; if(0 == nrEnvelopes){ return 0 ;} // sort on ascending w and descend h when same w auto sortPred = [](const pair<int, int> &wh1, const pair<int, int> &wh2) -> bool { int w1 = wh1.first , w2 = wh2.first, h1 = wh1.second, h2 = wh2.second; if(w1 < w2){ return true ;} // ascending on w else if(w1 == w2) { if(h1 < h2){ return false ;} // descend on h else { return true ;} } else { return false ; } } ; sort(envelopes.begin(), envelopes.end(), sortPred); // LIS on h vector<int> LISEndWithMinHeight(1, envelopes.at(0).second); for(size_t pos = 1 ; pos < nrEnvelopes; ++pos) { const pair<int, int> curEnvelope = envelopes.at(pos); int curHeight = curEnvelope.second; int LISPos = binarySearch(LISEndWithMinHeight, curHeight); if(LISPos == LISEndWithMinHeight.size()){ LISEndWithMinHeight.push_back(curHeight); } else { assert(LISPos < LISEndWithMinHeight.size()); LISEndWithMinHeight.at(LISPos) = curHeight; } } return LISEndWithMinHeight.size(); } private : int binarySearch(const vector<int> &sortedArray, int target) { int sz = sortedArray.size() ; int low = 0 , high = sz - 1; while(low <= high) { int mid = low + (high - low)/2 ; int midVal = sortedArray.at(mid); if(target > midVal){ low = mid + 1; } else if(target < midVal){ high = mid - 1 ;} else { return mid ;} } return low; // low = high + 1 } };
相关文章推荐
- leetcode 179 Largest Number
- leetcode 24 Swap Nodes in Pairs
- leetcode 2 Add Two Numbers 方法1
- leetcode 2 Add Two Numbers 方法2
- leetcode----Longest Substring Without Repeating Characters
- [LeetCode]47 Permutations II
- [LeetCode]65 Valid Number
- [LeetCode]123 Best Time to Buy and Sell Stock III
- [LeetCode] String Reorder Distance Apart
- [LeetCode] Sliding Window Maximum
- [LeetCode] Find the k-th Smallest Element in the Union of Two Sorted Arrays
- [LeetCode] Determine If Two Rectangles Overlap
- [LeetCode] A Distance Maximizing Problem
- leetcode_linearList
- leetcode_linearList02
- 021-Merge Two Sorted Lists(合并两个排好序的单链表);leetcode
- LeetCode[Day 1] Two Sum 题解
- LeetCode[Day 2] Median of Two Sorted Arrays 题解
- LeetCode[Day 3] Longest Substring Without... 题解
- LeetCode [Day 4] Add Two Numbers 题解