由买买提看人间百态

boards

本页内容为未名空间相应帖子的节选和存档,一周内的贴子最多显示50字,超过一周显示500字 访问原贴
JobHunting版 - 问一道面试题
相关主题
狗家 题 讨论Maximum Sum of Increasing Sequence
问一个经典题面试题count # of increasing subsequences of String求解
最长递增子array的算法转一些我blog上以前总结题目的日记(四)
Goog面试挂了,回报一下本版google题
问个最长递增序列的问题career cup book v4 9.7 题
这道题版上有讨论过吗?问个算法题5
严格单调递增的最长子序列fb电面第一轮
关于最长递增子序列的问题。分享Imo电面题
相关话题的讨论汇总
话题: rubber话题: src话题: binary话题: left话题: element
进入JobHunting版参与讨论
1 (共1页)
l**d
发帖数: 746
1
一个任意的数组,找出一个严格单调递增的最长子序列。
例如: { 3, 0, 1, 7, 2, 4, 9, 10, 5, 6, 8 } –> output: {0, 1, 2, 4, 5, 6, 8}
网上看到人说有个很简洁巧妙的算法,能在O(N log N)时间和O(N)空间做出来!方法就
是始终保持一个单增的序列,然后新来的数如果比当前最大还大就append在后面,否则
在单增序列里面做binary search,替换相应位置的数。
比如给定src[ ]:
3, 0, 1, 7, 2, 4, 9, 10, 5, 6, 8
定义一个新数组,value a[i]是当前数src[i]在包含自己的最长序列里的index。如果
src[i] > src[i-1], 那么a[i] = a[i-1] + 1, 否则,binary search 找到src[i] <
src[k-1],
src: 3, 0, 1, 7, 2, 4, 9, 10, 5, 15, 8
a: 1 1 2 3 3 4 5 6 5 7 6
可是我觉得这个方法不对啊,举个简单例子:给
src: {7, 8, 1, 10}
a: 1 2 1 ?
按照他的算法,到10的时候src[i] > src[i-1], 那么a[i] = a[i-1] + 1
可是10应该是从前面8开始算。那个binary search 怎么回事,我也没看明白。
d*******3
发帖数: 58
2
nlogn的不是这么做的,你想想你的a数组都不是有序的,怎么能binary search呢?
nlogn的是用数组a[i] 保存长度为i的递增序列末尾的最小元素,后面通过二分查找来
维护这个递增数组。
你的例子里不太明显,我换个
src:
2 9 7 3 8 5 10
a id:
0 1 2 3 4
2
2 9
2 7
2 3
2 3 8
2 3 5
2 3 5 10
这样最后递增序列长度为4
s**x
发帖数: 7506
3
Solution 2:
O(n log k) algorithm. K is the length of We have elements.
Assume we already have an increasing sequence: A1, A2, A3, …., for any
given element E, we either
can simply append E to make the list longer,
Do a binary search to find a position j such that A[j] < E < A[j+1], update
A[j+1] to E, so A[1..j+1] can get longer later with new element.
Another list P is used to stores the position of the predecessor element
in the longest increasing subsequence.
#include
using namespace std;
void find_lis(vector &a,
vector &b)
{
vector p(a.size());
int u, v;
if (a.empty()) return;
b.push_back(0);
for (size_t i = 1; i < a.size(); i++) {
/* If next element a[i] is greater than last element of
current longest subsequence a[b.back()], just push it at back of "b" and
continue */
if (a[b.back()] < a[i]) {
p[i] = b.back(); b.push_back(i);
continue;
}
/* Binary search to find the smallest element referenced by b which
is just bigger than a[i]
Note : Binary search is performed on b (and not a). Size of b is
always <=k and hence contributes O(log k) to complexity. */
for (u = 0, v = b.size()-1; u < v;) {
int c = (u + v) / 2;
if (a[b[c]] < a[i]) u=c+1; else v=c;
}
/* Update b if new value is smaller then previously referenced
value */
if (a[i] < a[b[u]]) {
if (u > 0) p[i] = b[u-1];
/* this will not corrupt existing LIS which is tracked by list p. */
b[u] = i;
}
} // end for loop
for (u = b.size(), v = b.back(); u--; v = p[v])
b[u] = v;
}
s**x
发帖数: 7506
4
这个题挺难的, 忘了从哪 找到的 code, 看了好多遍才看懂。
d**********x
发帖数: 4083
5
http://dp2.me/blog/?p=144

【在 s**x 的大作中提到】
: 这个题挺难的, 忘了从哪 找到的 code, 看了好多遍才看懂。
z****p
发帖数: 18
6

I figured out an O(n log n) algorithm. Obviously it's not as efficient as
duckling3's solution.
-First, sort the elements, which takes O(n log n)
-Second, visit the elements from the smallest to the largest, along the
visits, stretch several "rubber bands" (where the number of rubber bands is
up to K, with K being the size of the resulting max subsequence)
++all the rubber bands have their "right ends" at position N (outside the
array)
++we try to stretch the "left ends" of the rubber bands to as far left as
possible
++the 1st rubber band is longer than the 2nd one, which in turn is longer
than the 3rd one, and so on
++we use a binary tree to store the rubber bands' left ends, where the index
key is the location of the left ends
-When visiting the next element (according to the sorted order),
say it's position in the array is j
++we use a binary search to find the rubber band whose left end is
immediately to the right of j
++if j is smaller than the left end of the 1st rubber band,
we simply stretch the 1st rubber band by changing the left end of it to j,
++if j is bigger than the left ends of all the current rubber bands, we
start a new rubber band, and set its left end to j
++otherwise, we stretch the rubber band whose left end is immediately on
the right of j, by moving the rubber band's left end to j
-After visiting all the elements in sorted order and stretching the rubber
bands along the visits, the number of rubber bands K is the number
of elements in the max increasing subsequence.
-However, to get the exact subsequence, we have to revise the above
algorithm by adding a bookkeeping: when we stretch the k-th rubber band, we
need to
remember the location of the current location of the left end of the (k-1)-
th rubber band. Then we can trace back the bookkeeping pointers starting
from
that of the K-th rubber band.

【在 d*******3 的大作中提到】
: nlogn的不是这么做的,你想想你的a数组都不是有序的,怎么能binary search呢?
: nlogn的是用数组a[i] 保存长度为i的递增序列末尾的最小元素,后面通过二分查找来
: 维护这个递增数组。
: 你的例子里不太明显,我换个
: src:
: 2 9 7 3 8 5 10
: a id:
: 0 1 2 3 4
: 2
: 2 9

1 (共1页)
进入JobHunting版参与讨论
相关主题
分享Imo电面题问个最长递增序列的问题
这段LIS为啥崩溃?这道题版上有讨论过吗?
一道 facebook 电面题严格单调递增的最长子序列
被简单题给虐了。关于最长递增子序列的问题。
狗家 题 讨论Maximum Sum of Increasing Sequence
问一个经典题面试题count # of increasing subsequences of String求解
最长递增子array的算法转一些我blog上以前总结题目的日记(四)
Goog面试挂了,回报一下本版google题
相关话题的讨论汇总
话题: rubber话题: src话题: binary话题: left话题: element