一、排序子序列
题目解析
(图示:数组划分示例)
一个数组的连续子序列,如果这个子序列是非递增或者非递减的;这个连续的子序列就是排序子序列。
现在给定一个数组,然后让我们判断这个子序列可以划分成多少个排序子序列。
例如:
1 2 3 2 2 1可以划分成1 2 3和2 2 1两个排序子序列
算法思路
对于这道题,思路就很简单了:
暴力解法
从
0位置开始遍历,寻找一段连续子序列,直到这一段子序列不满足排序子序列的条件,即找到了一个排序子序列;然后继续从上次遍历结束位置接着遍历数组,寻找下一个子序列。
贪心优化:
当我们遍历到数组中数值相同的区域时,我们要知道,要找的子序列是非递增或者非递减的;
所以这一段相等的序列,我们可以加到前面或者后面的任意序列中。
所以我们在遇到数值相等的子序列时,继续向后遍历即可。
但是这样我们会发现两个问题:
如果数组刚开始位置的数据是相等的,我们不知道这段子序列是非递增的还是非递减的;我们在遍历过程中会用到下一个位置的值来判断是非递增还是非递减,那最后一个位置该怎么办?
对于数组开头的相等子序列,我们可以直接跳过,因为这一段相等的序列可以加到后面的子序列中;
而对于最后一个位置,如果它不能和前面序列组成一个排序子序列,那就只能让它自己组成一个排序子序列了。
(图示:边界情况处理)
代码实现
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int arr[N];
int n;
int main() {
cin >> n;
for (int i = 0; i < n; i++) cin >> arr[i];
int ret = 0;
for (int i = 0; i < n; i++) {
if (i == n - 1) {
ret++;
break;
}
if (arr[i] < arr[i + 1]) {
(i < n && arr[i] <= arr[i + ]) i++;
ret++;
} (arr[i] > arr[i + ]) {
(i < n && arr[i] >= arr[i + ]) i++;
ret++;
} {
(i < n && arr[i] == arr[i + ]) i++;
}
}
cout << ret << endl;
;
}


