我可以通过普通函数和递归函数打印LIS的长度。但我想在C ++中打印给定数组中的LIS子序列索引。
这是我找到LIS长度的函数:
int lis( int *arr, int n )
{
int *lis, i, j, max = 0;
lis = (int*) malloc ( sizeof( int ) * n );
for ( i = 0; i < n; i++ )
lis[i] = 1;
for ( i = 1; i < n; i++ )
for ( j = 0; j < i; j++ )
if ( arr[i] > arr[j] && lis[i] < lis[j] + 1)
lis[i] = lis[j] + 1;
for ( i = 0; i < n; i++ )
if ( max < lis[i] )
max = lis[i];
/* Free memory to avoid memory leak */
free( lis );
return max;
}
此处array[10]={7 6 2 3 4 1 8 5 9 10}
此处LIS Length=6
我想打印{2 3 4 6 8 9}
array[10]
(它不是它的arrray索引的序列,我想要打印的内容)
答案 0 :(得分:5)
在为每个索引计算lis之后,取tmp值等于max,在lis数组上向后移动,每次找到等于max的元素时,将该索引添加到答案并减去tmp。因此,您将以相反的顺序获取索引数组。
示例代码:
int tmp = max;
std::vector<int> indexes;
for( i = n - 1; i >= 0; --i )
if( lis[ i ] == tmp )
{
indexes.push_back( i );
--tmp;
}
std::reverse( indexes.begin(), indexes.end());
答案 1 :(得分:1)
要按顺序打印,您可以使用递归方法:调用:printLIS(lis,lis.length -1,arr,max)
public static void printLIS(int[] lis, int lisIndex, int[] arr, int max) {
if(max == 0) {
return;
}
if(lis[lisIndex] == max) {
printLis(lis,lisIndex-1, arr, max-1);
System.out.print(arr[lisIndex] + " ");
} else {
printLis(lis,lisIndex-1, arr, max);
}
}
答案 2 :(得分:1)
void solution() {
int n;
cin >> n;
vector<int> v(n);
for (int &x : v) cin >> x;
vector<int> dp(n, 1);
int i = 0, j = 1;
vector<int> par(n);
for (int i = 0; i < n; i++) {
par[i] = i;
}
for (int j = 1; j < n; j++) {
for (int i = 0; i < j; i++) {
if (v[j] > v[i] && dp[j] < dp[i] + 1) {
dp[j] = dp[i] + 1;
par[j] = i;
}
}
}
int mx = 1, idx = 0;
for (int i = 0; i < n; i++) {
if (dp[i] > mx) {
mx = dp[i];
idx = i;
}
}
cout << mx << "\n";
vector<int> seq;
while (true) {
seq.pb(v[idx]);
if (par[idx] == idx) break;
idx = par[idx];
}
reverse(seq.begin(), seq.end());
for (int i = 0; i < mx; i++) {
cout << seq[i] << " ";
}
}
维护一个父级数组,然后从LIS逐个父级终止的索引向后退,直到到达parent [index] = index的索引。
答案 3 :(得分:0)
int lis( int *arr, int n )
{
int *lis, i, j, max = 0, max_index = 0;
int *print = (int*)malloc(sizeof(int)*n);
lis = (int*) malloc ( sizeof( int ) * n );
for ( i = 0; i < n; i++ ){
lis[i] = 1;
print[i] = -1
}
for ( i = 1; i < n; i++ )
for ( j = 0; j < i; j++ )
if ( arr[i] > arr[j] && lis[i] < lis[j] + 1){
lis[i] = lis[j] + 1;
print[i] = j;
}
for ( i = 0; i < n; i++ ){
if ( max < lis[i] ){
max = lis[i];
max_index = i;
}
}
while(max_index >=0){
printf("%d ",lis[max_inc_index]);
max_index = print[max_index];
}
/* Free memory to avoid memory leak */
free( lis );
return max;
}
使用另一个跟踪索引的数组,这些索引是最长子序列的一部分,然后遍历数组以打印所有相应的元素。
答案 4 :(得分:0)
可以声明动态数组,其长度等于递增序列的最大长度。阵列ANS将保持最长的增长序列。
int *ans=(int*)malloc(sizeof(int)*max);
临时变量用于保持数组中最大长度的索引。
int index;
int length; //used to fill array ANS in reverse order.
for ( i = 0; i < n; i++ )
{
if ( max < lis[i] )
{
max = lis[i];
index=i;
}
}
length=max;
ans[length-1]=arr[index]; //filling array from the last
//last element will be the greatest element
length--;
while(index>0)
{
for(i=index-1;i>=0;i--)
{
if(lis[i]+1==lis[index] && arr[i]<arr[index])
{
ans[length-1]=arr[i];
index=i;
length--;
break;
}
}
}
for(i=0;i<max;i++)
{
printf("%d",ans[i]);
}
这里的复杂度是O(n)而不是O(n2),即使它可能正在使用两个循环,因为我们在每次输入块时都将索引值更改为i。
答案 5 :(得分:0)
不是最好的方法,但是您可以尝试...
int lis(int ar[], int n) {
int max = INT_MIN;
int* lis = new int[n];
int* sub_arr = new int[n];
for (int i = 0; i < n; ++i)
lis[i] = 1;
for (int i = 1; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if(ar[i] > ar[j] && lis[j] + 1 >= lis[i]) {
lis[i] = lis[j] + 1;
sub_arr[i] = j;
}
}
}
for (int i = 0; i < n; ++i) {
if(max < lis[i])
max = ar[i];
}
int k = 0;
stack <int> st;
for (int i = 0; i < n; ++i) {
if(max == lis[i])
k = i;
}
cout << "Longest Incresing Subsequence : ";
st.push(k);
while(k > 0) {
st.push(sub_arr[k]);
k = sub_arr[k];
}
while (!st.empty()) {
cout << ar[st.top()] << ' ';
st.pop();
}
cout << endl;
return max;
}
答案 6 :(得分:0)
如果有人对Java版本感兴趣。评论了解释。
rf_grid= {"n_estimators": np.arange(10,100,10),
"max_depth": [None,3,5,10],
"min_samples_split": np.arange(2,20,2),
"min_samples_leaf" : np.arange(1,20,2),
"max_features": [0.5,1,'sqrt','auto'],
"max_samples" : [100]