鉴于以下问题,
给定长度为n的整数A的数组,找到最长的序列{i_1,...,i_k},使得i_j&lt;对于[1,k-1]中的任何j,i_(j + 1)和A [i_j] <= A [i_(j + 1)]。
这是我的解决方案,这是正确的吗?
max_start = 0; // store the final result
max_end = 0;
try_start = 0; // store the initial result
try_end = 0;
FOR i=0; i<(A.length-1); i++ DO
if A[i] <= A[i+1]
try_end = i+1; // satisfy the condition so move the ending point
else // now the condition is broken
if (try_end - try_start) > (max_end - max_start) // keep it if it is the maximum
max_end = try_end;
max_start = try_start;
endif
try_start = i+1; // reset the search
try_end = i+1;
endif
ENDFOR
// Checking the boundary conditions based on comments by Jason
if (try_end - try_start) > (max_end - max_start)
max_end = try_end;
max_start = try_start;
endif
不知何故,我不认为这是一个正确的解决方案,但我找不到反对这个解决方案的反例。
任何人都可以提供帮助吗?
谢谢
答案 0 :(得分:5)
我没有看到你的算法有任何回溯,它似乎适用于非递减数字的连续块。如果我理解正确,请输入以下内容:
1 2 3 4 10 5 6 7
您的算法将返回1 2 3 4 10
而不是1 2 3 4 5 6 7
。
尝试使用dynamic programming找到解决方案。
答案 1 :(得分:2)
你错过了最后一次迭代没有破坏条件的情况:
1, 3, 5, 2, 4, 6, 8, 10
除非您的情况被破坏,否则您永远不会将try_start
和try_end
宣传给max_start
和max_end
。您需要在循环结束时执行相同的检查。
答案 2 :(得分:1)
好吧,看起来你正在找到序列的开始和结束,这可能是正确的,但它不是被问到的。我从阅读http://en.wikipedia.org/wiki/Longest_increasing_subsequence开始 - 我相信这是被问到的问题,这是一个相当众所周知的问题。一般不能在线性时间内解决,也需要某种形式的动态编程。 (维基百科上的算法也有一个更简单的n ^ 2变体 - 只需进行线性扫描而不是二分搜索。)
答案 3 :(得分:-1)
#include <algorithm>
#include <vector>
#include <stdio.h>
#include <string.h>
#include <assert.h>
template<class RandIter>
class CompM {
const RandIter X;
typedef typename std::iterator_traits<RandIter>::value_type value_type;
struct elem {
value_type c; // char type
explicit elem(value_type c) : c(c) {}
};
public:
elem operator()(value_type c) const { return elem(c); }
bool operator()(int a, int b) const { return X[a] < X[b]; } // for is_sorted
bool operator()(int a, elem b) const { return X[a] < b.c; } // for find
bool operator()(elem a, int b) const { return a.c < X[b]; } // for find
explicit CompM(const RandIter X) : X(X) {}
};
template<class RandContainer, class Key, class Compare>
int upper(const RandContainer& a, int n, const Key& k, const Compare& comp) {
return std::upper_bound(a.begin(), a.begin() + n, k, comp) - a.begin();
}
template<class RandIter>
std::pair<int,int> lis2(RandIter X, std::vector<int>& P)
{
int n = P.size(); assert(n > 0);
std::vector<int> M(n);
CompM<RandIter> comp(X);
int L = 0;
for (int i = 0; i < n; ++i) {
int j = upper(M, L, comp(X[i]), comp);
P[i] = (j > 0) ? M[j-1] : -1;
if (j == L) L++;
M[j] = i;
}
return std::pair<int,int>(L, M[L-1]);
}
int main(int argc, char** argv)
{
if (argc < 2) {
fprintf(stderr, "usage: %s string\n", argv[0]);
return 3;
}
const char* X = argv[1];
int n = strlen(X);
if (n == 0) {
fprintf(stderr, "param string must not empty\n");
return 3;
}
std::vector<int> P(n), S(n), F(n);
std::pair<int,int> lt = lis2(X, P); // L and tail
int L = lt.first;
printf("Longest_increasing_subsequence:L=%d\n", L);
for (int i = lt.second; i >= 0; --i) {
if (!F[i]) {
int j, k = 0;
for (j = i; j != -1; j = P[j], ++k) {
S[k] = j;
F[j] = 1;
}
std::reverse(S.begin(), S.begin()+k);
for (j = 0; j < k; ++j)
printf("%c", X[S[j]]);
printf("\n");
}
}
return 0;
}