最长连续递增子序列
最长连续递增子序列
给定一个顺序存储的线性表,请设计一个算法查找该线性表中最长的连续递增子序列。例如,(1,9,2,5,7,3,4,6,8,0)中最长的递增子序列为(3,4,6,8)。
输入格式:
输入第1行给出正整数n(≤10
5
);第2行给出n个整数,其间以空格分隔。
输出格式:
在一行中输出第一次出现的最长连续递增子序列,数字之间用空格分隔,序列结尾不能有多余空格。
输入样例:
15
1 9 2 5 7 3 4 6 8 0 11 15 17 17 10
输出样例:
3 4 6 8
代码长度限制
16 KB
时间限制
400 ms
内存限制
解题思路
将用户输入的数字存入数组后,判断相邻两个数字是否为前者小于后者的情况,如果属于那么计数器自增,否则计数器清零。同时需要定义一个变量max记录计数器的最大值,并且还需要一个变量记录最长连续递增子序列的起始下标用于遍历打印。
代码实现
#include<stdio.h>
void search_substring(int* arr, int length) {
int i, j, k, equal,first_index = 0, max = 1, count = 1;
int index[100000] = { 0 };
equal = 0;
for (i = 0; i < length - 1; i++) {
if (arr[i] < arr[i + 1]) {
count++; // 如果左边的数字小于右边的数字,计数器加一
if (count > max) { // 判断计数器的值是否大于最大值,如果是则替换MAX,并返回开始计算count的第一个数的下标。
max = count;
first_index = i - count + 2;
}
}
else
count = 1; // 如果左边的数字不小于右边的数字,计数器重置为一
}
// 打印结果
if (equal==length-1){
printf("%d", arr[0]);
return;
}
// 将结果存入数组
for (k = 0; k < max; k++)
index[k] = arr[first_index + k];
// 打印
for (j = 0; j < max; j++)
if (j == max - 1)
printf("%d", index[j]);
else
printf("%d%c", index[j], 32);
return;
}
int main() {
int n, i, num, arr[100000] = { 0 };
scanf("%d", &n);
for (i = 0; i < n; i++)
{
scanf("%d", &num);
arr[i] = num;
}
search_substring(arr, n);
return 0;
}
实现思路(2023年2月25日更新)
使用贪心的思路,局部最优:每次我们取子串的最大长度,全局最优:求出整个数组的最长递增子序列的最大长度。由于打印子串最少需要两个条件即:1.长度 2.起始/终止下标位置,或者 起始和终止下标位置。于是代码实现如下:
#include <iostream>
#include <vector>
using namespace std;
void dfs(vector<int>& nums)
{
int sub_length = 0;
int sub_end = 0;
int cur_start = 0;
for (int i = 1; i < nums.size(); i++)
{
if (nums[i] > nums[i - 1])
{
if (i - cur_start + 1 > sub_length)
{
sub_length = i - cur_start + 1;
sub_end = i;
}
}
else
{
cur_start = i;
}
}
for (int i = sub_end - sub_length + 1; i <= sub_end; i++)
{
cout << nums[i] << " ";
}
}
int main() {
vector<int> nums = { 1 ,9 ,2, 5, 7, 3, 4, 6, 8, 0, 11, 15, 17, 17, 10 };
dfs(nums);
return 0;
}

浙公网安备 33010602011771号