在神秘的数列世界中,有一个令人着迷的现象——“迷人数列”。当一个数列的最大值与最小值之差低于某个阈值时,它便被冠以“迷人”的称号。如今,我们面临一个挑战:给定一个数列和一个阈值,找出其中有多少个迷人的连续子序列。
一、问题解析
首先,让我们深入了解一下这个问题的核心。给定一个由n个整数组成的数列和一个阈值k,我们的目标是找出所有连续子序列,其最大值与最小值之差不超过k。例如,对于数列[1, 2, 3, 4]和阈值3,迷人的子序列有[1, 2]、[2, 3]和[3, 4],共计3个。
二、解题思路
为了解决这个问题,我们可以采用滑动窗口的方法。想象一下,我们有一个巨大的窗口,里面装满了数列中的数字。我们的任务是找出这个窗口内所有满足条件的连续子序列。
初始化窗口:我们首先设定窗口的左右边界为数列的起始和结束位置。
扩展窗口:然后,我们逐步向右移动窗口的右边界,每次移动都伴随着对窗口内数字的最大值和最小值的更新。
检查条件:在每次移动右边界后,我们检查当前窗口内的最大值与最小值之差是否满足阈值k的条件。
调整窗口:如果满足条件,我们将继续扩大窗口;如果不满足,我们需要缩小窗口(即移动左边界)直到满足条件为止。
计数迷人子序列:每当窗口满足条件时,我们就找到了一个迷人的连续子序列。我们将这些子序列的数量累加起来,得到最终的答案。
三、代码实现
下面是使用C++实现上述思路的代码:
# include <iostream>
# include <vector>
# include <algorithm>
using namespace std;
int solution(int n, int k, vector<int>& sequence) {
int left = 0, right = 0;
int result = 0;
int min_val = sequence[0], max_val = sequence[0];
while (left < n && right < n && left <= right) {
min_val = min(min_val, sequence[right]);
max_val = max(max_val, sequence[right]);
if ((max_val - min_val) <= k) {
result += (right - left + 1);
right++;
} else {
left++;
min_val = *min_element(sequence.begin() + left, sequence.begin() + right + 1);
max_val = *max_element(sequence.begin() + left, sequence.begin() + right + 1);
}
}
return result;
}
int main() {
vector<int> sequence1 = {3, 1, 2, 4};
vector<int> sequence2 = {7, 3, 5, 1, 9};
vector<int> sequence3 = {2, 2, 3, 1, 1, 2};
cout << (solution(4, 2, sequence1) == 8) << endl; // true
cout << (solution(5, 3, sequence2) == 6) << endl; // true
cout << (solution(6, 1, sequence3) == 12) << endl; // true
return 0;
}
四、代码详解
在这段代码中,我们使用了min_element
和max_element
函数来快速找到当前窗口内的最小值和最大值。这两个函数都是C++标准库中的算法,非常实用。
当我们发现当前窗口的最大值与最小值之差小于等于k时,我们就知道这个窗口内的所有子序列都是迷人的。此时,我们将结果增加窗口内所有可能的子序列数量(即right - left + 1
),然后将右边界向右移动一位继续检查。
如果当前窗口不满足条件,我们需要将左边界向右移动一位,并重新计算窗口内的最小值和最大值。这样,我们就能逐步缩小范围,直到找到所有满足条件的迷人子序列。
通过这种方法,我们能够在较短的时间内解决这个问题,而且代码结构清晰易懂。希望这篇文章能帮助你更好地理解迷人数列及其解决方法!
声明:
1、本博客不从事任何主机及服务器租赁业务,不参与任何交易,也绝非中介。博客内容仅记录博主个人感兴趣的服务器测评结果及一些服务器相关的优惠活动,信息均摘自网络或来自服务商主动提供;所以对本博客提及的内容不作直接、间接、法定、约定的保证,博客内容也不具备任何参考价值及引导作用,访问者需自行甄别。
2、访问本博客请务必遵守有关互联网的相关法律、规定与规则;不能利用本博客所提及的内容从事任何违法、违规操作;否则造成的一切后果由访问者自行承担。
3、未成年人及不能独立承担法律责任的个人及群体请勿访问本博客。
4、一旦您访问本博客,即表示您已经知晓并接受了以上声明通告。
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。
Copyright 2005-2024 yuanmayuan.com 【源码园】 版权所有 备案信息
声明: 本站非腾讯QQ官方网站 所有软件和文章来自互联网 如有异议 请与本站联系 本站为非赢利性网站 不接受任何赞助和广告