[英]How to find the longest increasing subsequence without sorting?
我想找到最长的递增子序列而不对其进行排序,然后对期间的数字求和,例如:
12, 15, 16, 4, 7, 10, 20,25
12,15,16
是递增子序列。4,7,10,20
是另一个增加的子序列。 但由于4,7,10,20,25
是5
元素,而12,15,16
是3
,小于4
,因此 output 应该是较长周期的总和,即5
元素的总和66
。
怎么可能使用c来完成这样的事情? 我是 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;
}
你真的需要两个循环。
一种遍历所有元素。 这是序列的“起始”索引。
然后,一个内部循环从开头右侧的一个元素开始。 它循环到数组的末尾,但如果它发现当前元素顺序不对则停止。
第二次循环结束后,这两个索引的差就是序列长度。
这是一些重构代码。 是这样注释的:
#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;
}
这是程序 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
更新:
上述的[相当大的]加速是改变:
for (int ilhs = 0; ilhs < count; ++ilhs) {
进入:
for (int ilhs = 0; ilhs < count; ilhs = irhs) {
并且,移动int irhs;
在外环之上。
这将时间从 O(n^2) 减少到 O(n)
这是一种可能的算法的概述,该算法将使用一个循环来解决它。
建筑模块:
longest_seq
。longest_sum
。running_seq
。running_sum
。从初始化开始:
longest_seq = 0
longest_sum = 0
然后初始化运行变量来处理第一个元素。 创建以下循环的方式应该清楚原因。
running_seq = 1
running_sum = arr[0]
现在到了有趣的部分:
i
从1
(不像往常一样是0
,我们在循环之前处理了第一个元素)循环到arr
中的元素数减去1
。
arr[i]
大于arr[i-1]
(前一个元素),则运行序列仍在继续,因此
running_seq
增加1
。arr[i]
不大于arr[i-1]
,则运行序列被破坏,因此
running_seq
是否大于longest_seq
。 如果是:
running_seq
和running_sum
保存到longest_seq
和longest_sum
。running_seq = 1
和running_sum = 0
。arr[i]
添加到running_sum
循环完成后,您需要再次检查running_seq
是否大于longest_seq
(并保存值以防万一)以防最长序列恰好位于数组的末尾。
完成后的答案在longest_seq
和longest_sum
中。
一个有细微差别的变体是在更新running_sum
方面稍微改变循环:
i
从1
(不像往常一样是0
,我们在循环之前处理了第一个元素)循环到arr
中的元素数减去1
。
arr[i]
大于arr[i-1]
(前一个元素),则运行序列仍在继续,因此
running_seq
增加1
。arr[i]
添加到running_sum
arr[i]
不大于arr[i-1]
,则运行序列被破坏,因此
running_seq
是否大于longest_seq
。 如果是:
running_seq
和running_sum
保存到longest_seq
和longest_sum
。running_seq = 1
和running_sum = arr[i]
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.