[英]How to find the longest increasing subsequence without sorting?
I want to find the longest increasing subsequence without sorting it, and to then sum the numbers of the period, for example like:我想找到最长的递增子序列而不对其进行排序,然后对期间的数字求和,例如:
12, 15, 16, 4, 7, 10, 20,25
12,15,16
is an increasing subsequence. 12,15,16
是递增子序列。4,7,10,20
is another increasing subsequence. 4,7,10,20
是另一个增加的子序列。 but since 4,7,10,20,25
are 5
elements and 12,15,16
are 3
which is less than the 4
, the output should be the sum of the longer period which is the sum of the 5
elements, 66
.但由于
4,7,10,20,25
是5
元素,而12,15,16
是3
,小于4
,因此 output 应该是较长周期的总和,即5
元素的总和66
。
How could such a thing be done using c ?怎么可能使用c来完成这样的事情? I am new to C so this is all what I could think of.
我是 C 的新手,所以这就是我能想到的。
#include<stdio.h>
int main() {
int count = 0;
int n;
int max = 0;
scanf("%d", &n);
int arr[1000];
for(int i = 0;i<n;i++){
if(arr[i+1>arr[i])
count++;
if(count>max)
max = count;
}
You really need two loops.你真的需要两个循环。
One that iterates through all elements.一种遍历所有元素。 This is the "starting" index of a sequence.
这是序列的“起始”索引。
Then, an inner loop that starts at one element to the right of the start.然后,一个内部循环从开头右侧的一个元素开始。 It loops to the end of the array but stops if it sees the current element is out of sequence.
它循环到数组的末尾,但如果它发现当前元素顺序不对则停止。
After the second loop ends, the difference of these two indexes is the sequence length.第二次循环结束后,这两个索引的差就是序列长度。
Here is some refactored code.这是一些重构代码。 It is annotated:
是这样注释的:
#include <stdio.h>
int arr[] = { 17, 18, 19, 5, 6, 23, 24, 25, 24, 25, 17, 18, 19 };
// show -- print a sequence
void
show(int begidx,int count,const char *tag)
{
printf("%s: %d %d --",tag,begidx,count);
for (; count > 0; --count, ++begidx)
printf(" %d",arr[begidx]);
printf("\n");
}
// sum -- get sum of the sequence
int
sum(int begidx,int count)
{
int sum = 0;
for (; count > 0; --count, ++begidx)
sum += arr[begidx];
return sum;
}
int
main(void)
{
int count = sizeof(arr) / sizeof(arr[0]);
int maxlen = 0;
int maxidx = -1;
show(0,count,"ORIG");
// loop through all possible starting points for sequence
for (int ilhs = 0; ilhs < count; ++ilhs) {
int lval = arr[ilhs];
// loop through all numbers to the right of the starter
// stop at the array end or when we get a number that is out of sequence
int irhs;
for (irhs = ilhs + 1; irhs < count; ++irhs) {
int rval = arr[irhs];
// out of sequence -- we've hit the end
if (rval < lval)
break;
lval = rval;
}
// get length of the sequence we just saw
int curlen = irhs - ilhs;
// remember a larger sequence
if (curlen > maxlen) {
maxlen = curlen;
maxidx = ilhs;
show(maxidx,maxlen,"NEW");
}
}
// show the maximum sequence
show(maxidx,maxlen,"FINAL");
// sum the sequence
printf("SUM: %d\n",sum(maxidx,maxlen));
return 0;
}
Here is the program output:这是程序 output:
ORIG: 0 13 -- 17 18 19 5 6 23 24 25 24 25 17 18 19
NEW: 0 3 -- 17 18 19
NEW: 3 5 -- 5 6 23 24 25
FINAL: 3 5 -- 5 6 23 24 25
SUM: 83
UPDATE:更新:
A [considerable] speedup for the above is to change:上述的[相当大的]加速是改变:
for (int ilhs = 0; ilhs < count; ++ilhs) {
Into:进入:
for (int ilhs = 0; ilhs < count; ilhs = irhs) {
And, move the int irhs;
并且,移动
int irhs;
above the outer loop.在外环之上。
This reduces the time from O(n^2) to O(n)这将时间从 O(n^2) 减少到 O(n)
Here's an outline of one possible algorithm that will solve it using one loop.这是一种可能的算法的概述,该算法将使用一个循环来解决它。
Building blocks:建筑模块:
longest_seq
.longest_seq
。longest_sum
.longest_sum
。running_seq
.running_seq
。running_sum
.running_sum
。 Start by initializing:从初始化开始:
longest_seq = 0
longest_sum = 0
Then initialize the running variables to handle the first element.然后初始化运行变量来处理第一个元素。 The way the following loop is created should make it clear why.
创建以下循环的方式应该清楚原因。
running_seq = 1
running_sum = arr[0]
Now to the interesting part:现在到了有趣的部分:
i
, loop from 1
(not 0
as usual, we handled the first element before the loop) to the number of elements you have in arr
, minus 1
.i
从1
(不像往常一样是0
,我们在循环之前处理了第一个元素)循环到arr
中的元素数减去1
。
arr[i]
is greater than arr[i-1]
(the previous element), the running sequence is still going on, soarr[i]
大于arr[i-1]
(前一个元素),则运行序列仍在继续,因此
running_seq
by 1
.running_seq
增加1
。arr[i]
is not greater than arr[i-1]
, the running sequence is broken, soarr[i]
不大于arr[i-1]
,则运行序列被破坏,因此
running_seq
is greater than longest_seq
.running_seq
是否大于longest_seq
。 If it is:running_seq
and running_sum
to longest_seq
and longest_sum
.running_seq
和running_sum
保存到longest_seq
和longest_sum
。running_seq = 1
and running_sum = 0
.running_seq = 1
和running_sum = 0
。arr[i]
to running_sum
arr[i]
添加到running_sum
When the loop is done, you need to check if running_seq
is greater than longest_seq
again (and save the values in case it is) just in case the longest sequence happened to be at the end of the array.循环完成后,您需要再次检查
running_seq
是否大于longest_seq
(并保存值以防万一)以防最长序列恰好位于数组的末尾。
The answers when this is done are in longest_seq
and longest_sum
.完成后的答案在
longest_seq
和longest_sum
中。
A variant with a minor difference is to change the loop slightly with regards to the updating of running_sum
:一个有细微差别的变体是在更新
running_sum
方面稍微改变循环:
i
, loop from 1
(not 0
as usual, we handled the first element before the loop) to the number of elements you have in arr
, minus 1
.i
从1
(不像往常一样是0
,我们在循环之前处理了第一个元素)循环到arr
中的元素数减去1
。
arr[i]
is greater than arr[i-1]
(the previous element), the running sequence is still going on, soarr[i]
大于arr[i-1]
(前一个元素),则运行序列仍在继续,因此
running_seq
by 1
.running_seq
增加1
。arr[i]
to running_sum
arr[i]
添加到running_sum
arr[i]
is not greater than arr[i-1]
, the running sequence is broken, soarr[i]
不大于arr[i-1]
,则运行序列被破坏,因此
running_seq
is greater than longest_seq
.running_seq
是否大于longest_seq
。 If it is:running_seq
and running_sum
to longest_seq
and longest_sum
.running_seq
和running_sum
保存到longest_seq
和longest_sum
。running_seq = 1
and running_sum = arr[i]
.running_seq = 1
和running_sum = arr[i]
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.